используя область на ассоциации - PullRequest
11 голосов
/ 01 февраля 2011

Итак, у меня появилась эта безумная идея, что я хотел применить область действия к включенной ассоциации.Это то, что я понял, и, кажется, работает нормально:

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 (чтобы использовать ее в другом месте) и использовать ее в ассоциации события, у меня должно быть два метода в Race.Для каждой области.

Я уверен, что мог бы обернуть шаблон в плагин или что-то подобное, но я бы предпочел использовать нативный AR / ARel, если это возможно.Есть идеи для этого?

Ответы [ 3 ]

6 голосов
/ 01 февраля 2011

Этот код кажется слишком сложным.Предполагая, что ваша цель состоит в том, чтобы получить все события, которые содержат расы только с «медалями» за призы, разве простая 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, чтобы получитьплохие расы.

0 голосов
/ 30 января 2018

Вы можете использовать области действия на обеих моделях с методом merge .Это действительно удобно в этом случае:

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
0 голосов
/ 28 апреля 2017

Более современный способ выразить сферу вашей ассоциации заключается в следующем:

scope :bad_races, -> { joins(:races).where(races: { prizes: 'medals' }) }
...