我有一個連接表的(我認爲)相對簡單has_many :through
關係:RSpec的測試的has_many:通過和after_save的
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
然後第二測試失敗 - 即,關係仍然加到連接表,但是@thing.followers
返回一個空數組。此外,回調的那部分永遠不會被調用(就好像followers
在模型中是空的)。如果我在followers.each
行之前的回調中添加puts "HI"
,則「HI」出現在stdout上,所以我知道該回調被調用。如果我註釋掉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中失敗?我在做可怕的錯誤嗎?
更新
一切正常,如果我手動定義爲
def followers
user_following_thing_relationships.all.map{ |r| r.user }
end
這使我相信,也許我定義我has_many :through
與:source
不正確?
更新
我創建了一個小例子項目,並把它放在github上:https://github.com/dantswain/RspecHasMany
另一個更新
由於一噸@PeterNixey和@kikuchiyo對他們的建議下面。最終答案證明是兩個答案的組合,我希望我可以在他們之間分配信貸。我已經用我認爲是最乾淨的解決方案更新了github項目並推送了更改:https://github.com/dantswain/RspecHasMany
如果有人能夠給我一個關於這裏發生的事情的真實可靠解釋,我仍然會喜歡它。對我來說最麻煩的一點是,在最初的問題陳述中,如果我註釋了對followers
的引用,所有內容(除了回調本身的操作)都可以工作。
不錯!這幾乎奏效,但它不會運行回調。 – dantswain
真是痛苦。我已經在更新的答案中提出了另一個建議 –
double重載(在規範和回調中)都是必需的,但我還需要調用@ thing.save(或@ thing.run_callbacks(:save) )。我有點困惑 - 如果我已經解決了我的問題,那麼感謝你的建議和kikuchiyo的建議。 – dantswain