0

考虑以下

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加入engineers并施加一些限制的类中,但我正在寻找的是利用已经在Engineer类上定义的范围。

4

2 回答 2

1

You might want to try and flip this around, like you suggest:

Idea.popular.includes(:engineer).by_masters.order('engineers.age')

Where your by_masters scope looks something like:

scope :by_masters, -> { where: { engineers: { educational_level: 'master' } } }

It's the includes call that forces a JOIN that makes this possible.

于 2013-10-15T21:41:59.487 回答
0

You can use joins and merges here:

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
于 2013-10-15T21:52:49.110 回答