2011-02-01 6 views
11

Quindi ho avuto questa pazza idea di voler applicare un ambito a un'associazione inclusa. Questo è quello che ho capito, e sembra funzionare bene:utilizzando l'ambito su un'associazione

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

Il problema è che è davvero ottusa. Per avere lo scopo definito su Race (da usare altrove) e usarlo nell'associazione dell'Evento, devo avere due metodi su Race. Per ogni ambito.

Sono sicuro che potrei avvolgere il pattern in un plugin o qualcosa del genere, ma preferirei usare l'AR/ARel nativo, se possibile. Qualche idea per farlo?

risposta

6

Questo codice sembra eccessivamente complesso. Supponendo che il tuo obiettivo è quello di ottenere tutti gli eventi che contengono gare con solo "medaglie" per i premi, non sarebbe un semplice lavoro 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 

Poi si può solo correre Event.bad_races per ottenere i cattivi gare.

+7

"Così ho avuto la pazza idea di voler applicare un ambito a un'associazione inclusa." – jsharpe

+2

AFAIK si può ASCIUGARE questo codice rendendo 'bad' un ambito in' Race', e poi si dice 'races.bad'. O forse funziona solo con gli ambiti, non ho controllato :( –

+1

@AlexeiAverchenko Ma in questo caso, vuole gli eventi che hanno gare che soddisfano le condizioni (cioè non vuole solo gli oggetti Race, vuole gli oggetti Event appartengono a). –

0

A più aggiornate modo per esprimere la portata della vostra associazione è la seguente:

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

È possibile utilizzare gli ambiti su entrambi i modelli con merge metodo. In questo caso è molto utile:

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 
Problemi correlati