链接包含连接()和select()的多个范围

时间:2013-12-03 17:04:58

标签: ruby-on-rails rails-activerecord

我读到的所有内容都建议人们将“复杂”查询保留在控制器之外,并将它们放入模型的范围内。但是,在使用joins时,如何使用需要三个模型数据的查询来推荐这样做。例如,

class User < ActiveRecord::Base
  belongs_to :company
  belongs_to :profile
end

如果我们需要来自companies.name的{​​{1}}和profiles.city,我们可以将查询填充到控制器操作中,这很有效。

User

为了将其保留在控制器之外,我们可以定义一个命名范围,例如

User.joins(:company, :profile).select('users.*, companies.name as company_name, profiles.city as city').find(1)

并在控制器中使用scope :include_company_name_and_profile_city, -> { joins(:company, :profile).select('users.*, companies.name as company_name, profiles.city as city') }

但是,如果在不同时间我们需要只是公司名称或只是个人资料城市呢?我们可以定义两个范围并将它们链接起来吗?

User.include_company_name_and_profile_city.find(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') } 将产生一个在SELECT子句中包含两个User.include_company_name.include_profile_city.find(1)的查询。

users.*

推荐的处理方式是什么?

  1. 将所有SELECT users.*, companies.name as company_name, profiles.city as city, users.*, ...joins()来电置于控制器?
  2. 创建一个加载公共关联数据的范围,如果不使用该数据,则不关心可能的开销? (这是有缺陷的imo,见下文)
  3. 创建多个不包含select()的命名范围,并在控制器或默认范围内附加select('users.*')
  4. select子句中有多个select('users.*')是否重要?
  5. 如果人们推荐选项2,那么我们在其他模板中需要更多(不那么常见)的关联数据呢? (即users.*)。这将遇到上述相同的问题(select子句中的多个User.include_common_association_data.include_non_common_association_data.find(1))。

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解实际问题,但听起来你正在编写联接并选择ActiveRecord为你做所有这些事情?

这些是你的模特吗?

class User < ActiveRecord::Base
  belongs_to :company
  belongs_to :profile
end
...
class Company 
  has_many :users
end

class Profile
  has_many :users
end

所以如果你想这样做:

  

如果我们需要来自用户的companies.name和profiles.city,我们可以   把查询填充到控制器动作中,效果很好。

你可以通过Active Record关系获得那些:

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")

修改:如果您之前没有花时间,activerecord query interface指南非常有帮助。 此外,ActiveRecord在优化查询时非常聪明,如果你想看到它呈现的SQL使用rails控制台来查看,你可以不告诉它该做什么。