[rspec-devel] [ rspec-Feature Requests-6980 ] Can't set expectations on Rails association proxy object

noreply at rubyforge.org noreply at rubyforge.org
Thu Nov 30 21:43:38 EST 2006


Feature Requests item #6980, was opened at 2006-11-30 05:34
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=6980&group_id=797

Category: None
Group: None
Status: Open
>Priority: 1
Submitted By: Pat Maddox (pergesu)
Assigned to: Nobody (None)
Summary: Can't set expectations on Rails association proxy object

Initial Comment:
edge rails, 0.7.3

context "Given a call to destroy, a Person" do
  setup do
    @person = Person.create :name => "Me", :user_id => 1
    @person.add_item Item.new(:name => "Item")
  end

  specify "should destroy its items" do
    @person.items.should_receive(:delete_all)
    @person.destroy
  end
end

This assumes the following config in Person.rb
has_many :items, :dependent => :delete_all

The failure is:
NoMethodError in 'Given a call to destroy, a Person should destroy its items'
undefined method `receive?' for Item:Class

My best guess is that since items is a proxy class defined at runtime, the should_receive method isn't getting mixed into it.

----------------------------------------------------------------------

>Comment By: David Chelimsky (dchelimsky)
Date: 2006-12-01 02:43

Message:
Ugh!

In activerecord/lib/active_record/associations/association_proxy.rb:

class AssociationProxy #:nodoc:
  attr_reader :reflection
  alias_method :proxy_respond_to?, :respond_to?
  alias_method :proxy_extend, :extend
  instance_methods.each { |m| undef_method m unless m =~  /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ }

That last line removes all of the rspec methods. Even if I add ^should_ to the list of methods NOT to undef, I get an error saying that items won't respond_to :delete_all.

So Rails is doing a bunch of magic to get things to behave in a way that is somewhat different from how they LOOK like they behave.

I'd recommend checking the collection size before and after using should_change for now:

lambda { @person.destroy }.should_change(Item, :count).by(-1)

It is state-based, but at least you can DO it, and I'd rather focus our energies on getting the rails plugin to do things you can not do at all for the time being.

David


----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2006-11-30 23:41

Message:
Have you tried this against 1.1.6? Just curious.

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=6980&group_id=797


More information about the rspec-devel mailing list