web-dev-qa-db-fra.com

ActiveRecord, has_many: through et associations polymorphes

Gens,

Je veux m'assurer de bien comprendre cela. Et veuillez ignorer le cas de l'héritage ici (SentientBeing), en essayant plutôt de vous concentrer sur les modèles polymorphes dans has_many: through relations. Cela dit, considérez ce qui suit ...

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

Dans un monde parfait, j'aimerais, étant donné un widget et une personne, faire quelque chose comme:

widget.people << my_person

Cependant, lorsque je fais cela, j'ai remarqué que le "type" du "groupeur" est toujours nul dans widget_groupings. Cependant, si je fais quelque chose comme ceci:

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

Ensuite, tout fonctionne comme je m'y attendais normalement. Je ne pense pas avoir déjà vu cela se produire avec des associations non polymorphes et je voulais juste savoir si c'était quelque chose de spécifique à ce cas d'utilisation ou si je regardais potentiellement un bug.

Merci pour toute aide!

115
Cory

Il y a problème conn avec Rails 3.1.1 qui rompt cette fonctionnalité. Si vous rencontrez ce problème, essayez d'abord la mise à niveau, il a été corrigé dans 3.1.2

Tu es si proche. Le problème est que vous abusez de l'option: source. : la source doit pointer vers la relation polymorphe d'appartenance. Il vous suffit ensuite de spécifier: type_source pour la relation que vous essayez de définir.

Cette correction du modèle Widget devrait vous permettre de faire exactement ce que vous recherchez.

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
160
EmFi

Comme mentionné ci-dessus, cela ne fonctionne pas avec Rails 3.1.1 en raison d'un bogue sur: source, mais il est corrigé dans Rails 3.1.2

3
scottkf