考虑以下
class Engineer < ActiveRecord::Base
has_many :ideas
scope :masters, -> { where(educational_level: ["master", "candidate"]) }
end
class Idea < ActiveRecord::Base
belongs_to :engineer
scope :popular, -> { where("rating > ?", 4) }
end
现在,假设我要检索由工程师age
订购的工程师设想的所有流行创意。为简单起见,假设age
只是engineers
表中的整数列。
这样做的一种方法是首先获取工程师。
popular_ideas_by_educated_engineers = []
Engineer.masters.order("age").each do |engineer|
popular_ideas_by_educated_engineers += engineer.ideas.popular
end
这段代码有一个n + 1问题,因为想法并没有急切加载,整体感觉很笨拙。
我想以一种允许通过编写类似
的方式获得所需结果的方式编写代码Idea.popular.by_masters.order_by_engineer_age
这可能 - 如果是的话,怎么样?
我知道我可以将SQL硬编码到加入Idea
的{{1}}类中并施加一些限制,但我正在寻找的是利用已经在engineers
类上定义的范围
答案 0 :(得分:1)
你可能想尝试翻转它,就像你建议的那样:
Idea.popular.includes(:engineer).by_masters.order('engineers.age')
您的by_masters
范围看起来像:
scope :by_masters, -> { where: { engineers: { educational_level: 'master' } } }
includes
调用迫使JOIN
使这成为可能。
答案 1 :(得分:0)
您可以在此处使用联接和合并:
class Engineer < ActiveRecord::Base
scope :masters, -> { where(educational_level: ["master", "candidate"]) }
scope :ordered_by_age, -> { order(:age) }
end
class Idea < ActiveRecord::Base
belongs_to :engineer
scope :popular, -> { where("rating > ?", 4) }
scope :by_master, -> { joins(:engineer).merge(Engineer.masters) }
scope :order_by_engineer_age, -> { joins(:engineer).merge(Engineer.order_by_age) }
end