Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using scope on an association

So I got this crazy idea that I wanted to apply a scope to an included association. This is what I figured out, and it seems to work just fine:

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

The problem is that it's really obtuse. In order to have the scope defined on Race (to use elsewhere) and to use it on the Event's association I have to have two methods on Race. For each scope.

I'm sure that I could wrap the pattern into a plugin or some such, but I'd much rather use native AR/ARel if that's possible. Any ideas for doing that?

like image 250
jsharpe Avatar asked Feb 01 '11 05:02

jsharpe


2 Answers

This code seems overly complex. Assuming that your goal is to get all the events that contain races with only "medals" for prizes, wouldn't a simple scope work?

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

Then you can just run Event.bad_races to get the bad races.

like image 59
Dylan Markow Avatar answered Oct 23 '22 15:10

Dylan Markow


You can use scopes on both models with merge method. It's really handy in this case:

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
like image 38
Tetiana Chupryna Avatar answered Oct 23 '22 15:10

Tetiana Chupryna