ActiveRecord、has_many:through、および多態的な関連付け


117

フォーク、

これを正しく理解したことを確認したい。そして、ここでの継承のケース(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}) 

その後、すべてが通常どおりに機能します。これが多態性のない関連で発生するのを見たことがないと思いますが、これがこのユースケースに固有の何かであるかどうか、またはバグを監視している可能性があるかどうかを知りたいだけです。

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

回答:


162

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

ああ、痛々しいほど明白な私の神は、私がその上に艶をかけたとは信じられません。EmFiに感謝!
コリー

問題ありません。私が初めて遭遇したとき、私はこれをどうやってやるかについて約1日苦しんだと思います。それがチュートリアル/本に従うことを含まない、私がRailsで最初に行おうとしたことの1つであることを助けませんでした。
EmFi 2009年

1
scotkfが指摘するように、ActiveRecord 3.1.1には、この動作をブロックする回帰があります。3.1.2にアップグレードすると、このソリューションが機能するようになります。
EmFi

6
@Shtirlicが述べたのと同じこと。source_typeを指定しない方法があるので、結果セットが混在していますか?誰かがこれを解決した場合、方法を知りたいです。
デイモンAW

3
Rails 4.2.0でもまだ機能します。しかし、source_typeと2つの個別の関連付けなしでこれを実現する方法はありますか?
Emeka 2016

3

上で述べたように、これは:sourceのバグのためにRails 3.1.1では機能しませんが、Rails 3.1.2で修正されています。


-4

多くの:throughとpolymorphicが一緒に機能しません。それらに直接アクセスしようとすると、エラーがスローされます。私が間違っていない場合は、widget.peopleとpushルーチンを手書きする必要があります。

バグだとは思いません。まだ実装されていないものです。誰もが利用できるケースがあるので、この機能で見たと思います。


6
彼らは一緒に働きます。例:has_many:subscriptions、:as =>:subscribable has_many:subscribers、:through =>:subscriptions、:source =>:user
ScottJ

私は失敗するコードの例を近い将来に別の投稿としてスローします:)そのエラーを回避する方法を理解するために頭痛の多くを救うでしょう。
cgr 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.