私は(私が思うに)has_many :through
結合テーブルとの比較的単純な関係を持っています:
class User < ActiveRecord::Base
has_many :user_following_thing_relationships
has_many :things, :through => :user_following_thing_relationships
end
class Thing < ActiveRecord::Base
has_many :user_following_thing_relationships
has_many :followers, :through => :user_following_thing_relationships, :source => :user
end
class UserFollowingThingRelationship < ActiveRecord::Base
belongs_to :thing
belongs_to :user
end
そして、これらの rspec テスト (これらは必ずしも良いテストではないことはわかっています。何が起こっているかを説明するためのものです):
describe Thing do
before(:each) do
@user = User.create!(:name => "Fred")
@thing = Thing.create!(:name => "Foo")
@user.things << @thing
end
it "should have created a relationship" do
UserFollowingThingRelationship.first.user.should == @user
UserFollowingThingRelationship.first.thing.should == @thing
end
it "should have followers" do
@thing.followers.should == [@user]
end
end
これは、を参照するモデルに を追加するまで問題なく動作after_save
します。つまり、もしそうならThing
followers
class Thing < ActiveRecord::Base
after_save :do_stuff
has_many :user_following_thing_relationships
has_many :followers, :through => :user_following_thing_relationships, :source => :user
def do_stuff
followers.each { |f| puts "I'm followed by #{f.name}" }
end
end
その後、2 番目のテストは失敗します。つまり、関係は引き続き結合テーブルに追加され@thing.followers
ますが、空の配列が返されます。さらに、コールバックのその部分が呼び出されることはありません (あたかもfollowers
モデル内で空であるかのように)。puts "HI"
行の前にコールバックにa を追加するとfollowers.each
、「HI」が標準出力に表示されるので、コールバックが呼び出されていることがわかります。行をコメントアウトするとfollowers.each
、テストは再びパスします。
これをすべてコンソールから行うと、正常に動作します。つまり、できる
>> t = Thing.create!(:name => "Foo")
>> t.followers # []
>> u = User.create!(:name => "Bar")
>> u.things << t
>> t.followers # [u]
>> t.save # just to be super duper sure that the callback is triggered
>> t.followers # still [u]
これがrspecで失敗するのはなぜですか? 私はひどく間違ったことをしていますか?
アップデート
手動で次のように定義すると、すべてが機能Thing#followers
します
def followers
user_following_thing_relationships.all.map{ |r| r.user }
end
これは、おそらく私が my has_many :through
with を:source
間違って定義していると信じるように導きますか?
アップデート
最小限のサンプル プロジェクトを作成し、github に配置しました: https://github.com/dantswain/RspecHasMany
別のアップデート
@PeterNixey と @kikuchiyo の以下の提案に感謝します。最終的な答えは両方の答えの組み合わせであることが判明したので、それらの間でクレジットを分割できたらいいのにと思います。最もクリーンなソリューションと思われるもので github プロジェクトを更新し、変更をプッシュしました: https://github.com/dantswain/RspecHasMany
誰かがここで何が起こっているのかについて本当にしっかりした説明をしてくれるなら、私はまだそれが大好きです. 私にとって最も厄介な点は、最初の問題ステートメントで、への参照をコメントアウトした場合にすべて (コールバック自体の操作を除く) が機能する理由ですfollowers
。