2011-02-01 11 views
11

Więc mam ten szalony pomysł, że chciałem zastosować zakres do dołączonego stowarzyszenia. Właśnie to odkryłem i wygląda na to, że działa dobrze:używając zakresu w stowarzyszeniu

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

Problem polega na tym, że jest naprawdę tępy. Aby mieć zakres zdefiniowany w Race (do wykorzystania w innym miejscu) i używać go w związku Eventu, muszę mieć dwie metody w Race. Dla każdego zakresu.

Jestem pewien, że mógłbym zawinąć wzorzec w wtyczkę lub coś podobnego, ale wolałbym użyć natywnego AR/ARel, jeśli to możliwe. Jakieś pomysły na to?

Odpowiedz

6

Ten kod wydaje się zbyt skomplikowany. Zakładając, że Twoim celem jest, aby wszystkie wydarzenia zawierające wyścigi zawierały tylko "medale" na nagrody, czy nie byłaby to prosta robota 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 

Następnie można po prostu uruchomić Event.bad_races, aby uzyskać złe wyścigi.

+7

"Więc dostałem ten szalony pomysł, że chciałem zastosować zakres do dołączonego stowarzyszenia." – jsharpe

+2

AFAIK możesz osuszyć ten kod, nadając 'zły' zakres w' Wyścigu', a następnie po prostu wypowiedz 'races.bad'. A może działa tylko z lunetami, których nie sprawdziłem :( –

+1

@AlexeiAverchenko Ale w tym przypadku chce wydarzeń, które miały wyścigi spełniające warunki (tj. Nie chce tylko obiektów Race, chce obiektów Event oni należą do). –

0

Bardziej aktualne sposób wyrażania zakres swojego stowarzyszenia jest następujący:

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

Można używać zakresów w obu modelach z merge metody. Jest bardzo przydatny w tym przypadku:

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 
Powiązane problemy