2009-11-05 21 views
111

gente,ActiveRecord, has_many: a través, y polimórficos Asociaciones

quiere asegurarse de que entiendo esto correctamente. Y por favor ignore el caso de la herencia aquí (SentientBeing), tratando de enfocarse en modelos polimórficos en has_many: a través de las relaciones. Dicho esto, considere lo siguiente ...

class Widget < ActiveRecord::Base 
    has_many :widget_groupings 

    has_many :people, :through => :widget_groupings, :source => :person, :conditions => "widget_groupings.grouper_type = 'Person'" 
    has_many :aliens, :through => :widget_groupings, :source => :alien, :conditions => "video_groupings.grouper_type = 'Alien'" 
end 

class Person < ActiveRecord::Base 
    has_many :widget_groupings, :as => grouper 
    has_many :widgets, :through => :widget_groupings 
end 

class Alien < ActiveRecord::Base 
    has_many :widget_groupings, :as => grouper 
    has_many :widgets, :through => :widget_groupings 
end 

class WidgetGrouping < ActiveRecord::Base 
    belongs_to :widget 
    belongs_to :grouper, :polymorphic => true 
end 

En un mundo perfecto, me gustaría, dado un Widget y una persona, hacer algo como:

widget.people << my_person 

Sin embargo, cuando lo haga esto, he notado que el 'tipo' de 'grouper' siempre es nulo en widget_groupings. Sin embargo, si hago algo similar a lo siguiente:

widget.widget_groupings << WidgetGrouping.new({:widget => self, :person => my_person}) 

Entonces todo funciona como normalmente esperaba. No creo que haya visto esto ocurrir con asociaciones no polimórficas y solo quería saber si esto era algo específico de este caso de uso o si estoy potencialmente mirando un error.

¡Gracias por cualquier ayuda!

Respuesta

156

Hay un known issue con Rails 3.1.1 que rompe esta funcionalidad. Si tiene este problema primero intente actualizar, se ha solucionado en 3.1.2

Estás tan cerca. El problema es que estás haciendo un uso indebido de la opción: fuente. : source debe apuntar a la relación polimórfica belongs_to. Entonces, todo lo que necesita hacer es especificar: tipo_origen para la relación que está tratando de definir.

Esta solución al modelo de widget debería permitirle hacer exactamente lo que está buscando.

class Widget < ActiveRecord::Base 
    has_many :widget_groupings 

    has_many :people, :through => :widget_groupings, :source => :grouper, :source_type => 'Person' 
    has_many :aliens, :through => :widget_groupings, :source => :grouper, :source_type => 'Alien' 
end 
+0

¡Oh, Dios mío, es tan dolorosamente obvio que no puedo creer que haya pasado por alto! Gracias EmFi! – Cory

+0

No hay problema, creo que agonicé durante casi un día sobre cómo hacerlo la primera vez que lo encontré. No ayudó que fuera una de las primeras cosas que intenté hacer en Rails que no implicó seguir un tutorial/libro. – EmFi

+0

Gracias EmFi. – jdl

-3

tiene muchos: a través y polimórficos no funcionan juntos. Si intenta acceder a ellos directamente, debería arrojar un error. Si no me equivoco, tiene que escribir a mano widget.people y la rutina de inserción.

No creo que sea un error, es solo algo que aún no se ha implementado. Me imagino que lo vemos en la función, porque todos tienen un caso en el que podrían usarlo.

+5

Ellos trabajan juntos. Por ejemplo: has_many: suscripciones,: as =>: suscriptor has_many: suscriptores,: a través =>: suscripciones,: fuente =>: usuario – ScottJ

+0

Voy a arrojar un ejemplo de mi código que falla como una publicación separada en el cercano futuro :) Me ahorraría un montón de dolor de cabeza para descubrir cómo evitar ese error. – cgr

3

Como se mencionó anteriormente, esto no funciona con los carriles 3.1.1 debido a un error en: fuente, pero se fija en Rails 3.1.2

+0

https://github.com/rails/rails/issues/3271 – EmFi

Cuestiones relacionadas