2011-02-01 14 views
11

Así que tuve esta loca idea de que quería aplicar un alcance a una asociación incluida. Esto es lo que me di cuenta, y parece funcionar muy bien:usando el alcance en una asociación

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

El problema es que es muy obtuso. Para tener el alcance definido en Race (para usar en otro lugar) y usarlo en la asociación del Evento, tengo que tener dos métodos en Race. Para cada alcance

Estoy seguro de que podría envolver el patrón en un plugin o algo así, pero prefiero usar AR/ARel nativo si eso es posible. Alguna idea para hacer eso?

Respuesta

6

Este código parece demasiado complejo. Suponiendo que tu objetivo es obtener todos los eventos que contienen carreras con solo "medallas" para premios, ¿no funcionaría un simple 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 

continuación, sólo puede funcionar Event.bad_races para conseguir las malas carreras.

+7

"Así que tuve esta loca idea de que quería aplicar un alcance a una asociación incluida." – jsharpe

+2

AFAIK puedes SECAR este código haciendo que 'bad' sea un ámbito en' Race', y luego simplemente 'races.bad'. O tal vez solo funciona con alcances, no lo he comprobado :( –

+1

@AlexeiAverchenko Pero en este caso, él quiere que los eventos que tuvieron carreras satisfagan las condiciones (es decir, no solo quiere los objetos de la Carrera, quiere los objetos del Evento) pertenecen a). –

0

A más hasta la fecha de manera de expresar el alcance de su asociación es la siguiente:

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

Usted puede utilizar alcances en ambos modelos con merge método. Es realmente útil en este caso:

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 
Cuestiones relacionadas