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