I have an (I think) relatively straightforward has_many :through
relationship with a join table:
class User < ActiveRecord::Base
has_many :user
UPDATED ANSWER ** This passes rspec, without stubbing, running callbacks for save (after_save callback included ), and checks that @thing.followers is not empty before trying to access its elements. (;
describe Thing do
before :each do
@user = User.create(:name => "Fred");
@thing = Thing.new(:name => 'Foo')
@user.things << @thing
@thing.run_callbacks(:save)
end
it "should have created a relationship" do
@thing.followers.should == [@user]
puts @thing.followers.inspect
end
end
class Thing < ActiveRecord::Base
after_save :some_function
has_many :user_following_thing_relationships
has_many :followers, :through => :user_following_thing_relationships, :source => :user
def some_function
the_followers = followers
unless the_followers.empty?
puts "accessing followers here: the_followers = #{the_followers.inspect}..."
end
end
end
ORIGINAL ANSWER **
I was able to get things to work with the after_save callback, so long as I did not reference followers
within the body / block of do_stuff
. Do you have to reference followers
in the real method you are calling from after_save
?
Updated code to stub out callback. Now model can remain as you need it, we show @thing.followers is indeed set as we expected, and we can investigate the functionality of do_stuff / some_function via after_save in a different spec.
I pushed a copy of the code here: https://github.com/kikuchiyo/RspecHasMany
And spec passing thing* code is below:
# thing_spec.rb
require 'spec_helper'
describe Thing do
before :each do
Thing.any_instance.stub(:some_function) { puts 'stubbed out...' }
Thing.any_instance.should_receive(:some_function).once
@thing = Thing.create(:name => "Foo");
@user = User.create(:name => "Fred");
@user.things << @thing
end
it "should have created a relationship" do
@thing.followers.should == [@user]
puts @thing.followers.inspect
end
end
# thing.rb
class Thing < ActiveRecord::Base
after_save :some_function
has_many :user_following_thing_relationships
has_many :followers, :through => :user_following_thing_relationships, :source => :user
def some_function
# well, lets me do this, but I cannot use @x without breaking the spec...
@x = followers
puts 'testing puts hear shows up in standard output'
x ||= 1
puts "testing variable setting and getting here: #{x} == 1\n\t also shows up in standard output"
begin
# If no stubbing, this causes rspec to fail...
puts "accessing followers here: @x = #{@x.inspect}..."
rescue
puts "and this is but this is never seen."
end
end
end