我有一个(我认为)相对简单的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
to the 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
模型内为空)。如果我添加一个puts "HI"
在之前的回调中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 会失败?我做错了什么可怕的事情吗?
Update
如果我手动定义一切正常Thing#followers
as
def followers
user_following_thing_relationships.all.map{ |r| r.user }
end
这让我相信也许我正在定义我的has_many :through
with :source
错误地?
Update
我创建了一个最小的示例项目并将其放在 github 上:https://github.com/dantswain/RspecHasMany https://github.com/dantswain/RspecHasMany
另一个更新
非常感谢@PeterNixey 和@kikuchiyo 在下面提出的建议。最终的答案是两个答案的组合,我希望我可以在它们之间分配功劳。我已经用我认为最干净的解决方案更新了 github 项目并推送了更改:https://github.com/dantswain/RspecHasMany https://github.com/dantswain/RspecHasMany
如果有人能给我一个关于这里发生的事情的真正可靠的解释,我仍然会喜欢它。对我来说最麻烦的是,为什么在最初的问题陈述中,如果我注释掉对的引用,所有内容(除了回调本身的操作)都会起作用followers
.