14

所以我有一个疯狂的想法,我想将一个范围应用于包含的关联。这就是我想出来的,它似乎工作得很好:

class Event < ActiveRecord::Base
  has_many :races
  has_many :bad_races, :conditions => Race.bad_medals_sql, :class_name => "Race"
end

class Race < ActiveRecord::Base
  def self.bad_medals_sql
    arel_table[:prizes].eq('medals').to_sql
    # This returns a string
    # "`races`.`prizes` = 'medals'"
  end

  def self.bad_medals
    where(bad_medals_sql)
  end
end

Event.includes(:bad_races)
Reloading...
  Event Load (0.4ms)  SELECT `events`.* FROM `events`
  Race Load (0.5ms)  SELECT `races`.* FROM `races` WHERE (`races`.event_id IN (1,2,3,4) AND (`races`.`prizes` = 'medals'))

问题是它真的很钝。为了在 Race 上定义范围(在其他地方使用)并在 Event 的关联中使用它,我必须在 Race 上有两种方法。对于每个范围。

我确信我可以将模式包装到插件或类似的东西中,但如果可能的话,我更愿意使用原生 AR/ARel。有什么想法吗?

4

3 回答 3

7

这段代码似乎过于复杂。假设您的目标是获得所有包含比赛的赛事,其中只有“奖牌”作为奖品,这不是一个简单的scope工作吗?

class Event < ActiveRecord::Base
  has_many :races
  scope :bad_races, includes(:races).where("races.prizes=?", "medals")
end

class Race < ActiveRecord::Base
  belongs_to :event
end

然后你可以跑去Event.bad_races参加糟糕的比赛。

于 2011-02-01T05:30:13.307 回答
2

您可以在两个模型上使用合并方法的范围。在这种情况下真的很方便:

class Event < ActiveRecord::Base
  has_many :races
  scope :bad_races, -> { joins(:races).merge(Race.bad_medals) }
end

class Race < ActiveRecord::Base
  belongs_to :event
  scope :bad_medals, -> { where(price: 'medal') }
end
于 2018-01-30T11:15:52.987 回答
0

表达您的协会范围的最新方式如下:

scope :bad_races, -> { joins(:races).where(races: { prizes: 'medals' }) }
于 2017-04-28T08:44:21.630 回答