web-dev-qa-db-ja.com

ActiveRecord、has_many:through、およびポリモーフィックアソシエーション

皆さん、

これを正しく理解していることを確認したいです。そして、ここでは継承のケース(SentientBeing)を無視して、代わりにhas_many:through関係のポリモーフィックモデルに焦点を合わせてください。とはいえ、次のことを考慮してください...

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

完璧な世界では、ウィジェットと人を指定して、次のようなことをしたいと思います。

widget.people << my_person

ただし、これを行うと、widget_groupingsで 'grouper'の 'type'が常にnullであることに気付きました。ただし、次のような場合:

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

その後、すべてが正常に機能するはずです。私はこれが非多態的な関連で発生するのを見たことはないと思いますが、これがこのユースケースに固有のものであるか、潜在的にバグを見つめているのかを知りたいだけです。

助けてくれてありがとう!

115
Cory

既知の問題 with Rails 3.1.1はこの機能を中断します。この問題が発生している場合は、最初にアップグレードしてみてください。 3.1.2で修正されました

あなたはとても近いです。問題は、:sourceオプションを誤用していることです。 :sourceは、ポリモーフィックのbelongs_to関係を指す必要があります。その後、必要なのは、定義しようとしている関係に:source_typeを指定することだけです。

ウィジェットモデルのこの修正により、探しているものを正確に実行できるはずです。

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

前述のように、これはRails 3.1.1:sourceのバグが原因で機能しませんが、Rails 3.1.2で修正されました

3
scottkf