Ruby on rails 链接包含joins()和select()的多个作用域

Ruby on rails 链接包含joins()和select()的多个作用域,ruby-on-rails,rails-activerecord,Ruby On Rails,Rails Activerecord,我读到的每一篇文章都建议人们不要将“复杂”的查询放在控制器之外,并将它们放在模型的作用域中。但是,对于使用联接时需要来自三个模型的数据的查询,您建议如何执行此操作。比如说, class User < ActiveRecord::Base belongs_to :company belongs_to :profile end 例如,为了将其排除在控制器之外,我们可以定义一个命名范围 scope :include_company_name_and_profile_city, ->

我读到的每一篇文章都建议人们不要将“复杂”的查询放在控制器之外,并将它们放在模型的作用域中。但是,对于使用
联接时需要来自三个模型的数据的查询,您建议如何执行此操作。比如说,

class User < ActiveRecord::Base
  belongs_to :company
  belongs_to :profile
end
例如,为了将其排除在控制器之外,我们可以定义一个命名范围

scope :include_company_name_and_profile_city, -> { joins(:company, :profile).select('users.*, companies.name as company_name, profiles.city as city') }
在控制器中使用
用户。包括公司名称和城市概况。查找(1)

但如果在不同的时间,我们只需要公司名称或城市简介怎么办?我们能定义两个作用域并将它们链接起来吗

scope :include_company_name, -> { joins(:company).select('users.*, companies.name as company_name') }
scope :include_profile_city, -> { joins(:profile).select('users.*, profiles.city as city') }
调用
User.include\u company\u name.include\u profile\u city.find(1)
将生成一个包含两个
用户的查询。*
在SELECT子句中

选择users.*,companys.name作为公司名称,profiles.city作为城市,users.*,

建议的处理方法是什么

  • 是否将所有
    连接()
    选择()
    调用放入控制器中
  • 创建一个加载公共关联数据的作用域,如果该数据从未使用过,则不考虑可能的开销?(这是有缺陷的imo,见下文)
  • 创建不包含
    select('users.*')
    的多个命名作用域,并在控制器或默认作用域中追加
    select('users.*')
  • select子句中有多个
    用户。*
    是否重要

  • 如果人们推荐选项2,那么在其他模板中需要更多(不太常见)关联数据的情况下会怎么样?(即,
    User.include_common_association_数据。include_non_common_association_数据。find(1)
    )。这将受到上述相同问题的影响(select子句中有多个
    用户。*

    我不确定我是否理解实际问题,但听起来好像你在编写连接和选择,而ActiveRecord为你做了所有这些

    这些是你的模型吗

    class User < ActiveRecord::Base
      belongs_to :company
      belongs_to :profile
    end
    ...
    class Company 
      has_many :users
    end
    
    class Profile
      has_many :users
    end
    
    编辑以使用includes显示即时加载 您不需要一个作用域来确定这两个属性中的任何一个,除非还有更多。作用域基本上用于从属性中自动筛选

    scope :latest, order("created_at desc").limit(3)
    scope :city_present, where("city is not null")
    
    编辑:如果您以前没有花过时间,本指南非常有用。
    另外,ActiveRecord非常擅长优化查询,而无需您告诉它该做什么,如果您想查看它呈现的SQL,请使用rails控制台查看

    user=user.find(1)
    将执行一个查询,访问
    user.company.name
    将执行第二个查询(
    SELECT*FROM companys…
    ),
    user.profile.city
    将执行第三个查询(
    SELECT*FROM profiles…
    )。不过,您可以使用
    joins()
    select()
    使用
    User.joins(:company,:profile)。选择('users.*,companys.name as company\u name,profiles.city as city')。查找(1)
    ,这将在用户实例上添加
    company\u name
    city
    属性,同时只执行一个查询。是,但是,如果您急切地加载连接的对象,它将对所有三个对象执行一次查询,这样您就拥有了完全加载的对象,而不仅仅是在选择中提取细节。“Active Record允许您使用单个模型加载任意数量的关联。通过使用数组、哈希或嵌套的数组/哈希哈希以及includes方法进行查找调用。`”否。我假设人们专门为他们需要的数据编写每个作用域,但这会导致重复,我不喜欢这种情况。您看到我关于使用包含一次查询多个对象(在一个查询中)的观点了吗?
    user = User.find(whatever).includes(:company, :profile)
    user.company.name 
    user.profile.city
    
    scope :latest, order("created_at desc").limit(3)
    scope :city_present, where("city is not null")