Why is the behaviour of ActiveRecord method_missing different between rails 3.2 and 4.0?

I have been working on updating a rails application to 4.0 and spent
some
time getting to the bottom of why it wasn’t working.

What I found was, if a model has a method_missing definition then it is
called instead of any accessors. This causes any model set-up to fail.

The following example demonstrates the problem:

class Item < ActiveRecord::Base
attr_accessible :name, :content
store :content

def method_missing(id, *args)
puts “method missing: #{id}”
endend

In Rails 3.2.14:

$ rails consoleLoading development environment (Rails 3.2.14)2.0.0p247
:001 > x = Item.new(name: ‘foo’)
=> #<Item id: nil, name: “foo”, content: {}, created_at: nil,
updated_at: nil> 2.0.0p247 :002 >

and in Rails 4.0.0:

$ rails consoleLoading development environment (Rails 4.0.0)2.0.0p247
:001 > x = Item.new(name: ‘foo’)
method missing: name=
=> #<Item id: nil, name: nil, content: {}, created_at: nil, updated_at:
nil> 2.0.0p247 :002 >

In Rails 3.2.14, the name attribute is set to foo as is the intention.
In
Rails 4.0.0, however, see that method_missing is called and the
attribute
is not set.

I can work around this by manually invoking the upward method_missing
chain:

def method_missing(id, *args)
super
if respond_to? id
send(id,*args)
else
puts “method missing: #{id}”
end end

I don’t understand why this happens, or if I am doing something wrong.
Would someone with more knowledge of the internals be able to explain
this ?

On Thu, Aug 29, 2013 at 2:29 PM, starfry [email protected] wrote:

I have been working on updating a rails application to 4.0 and spent some
time getting to the bottom of why it wasn’t working.

What I found was, if a model has a method_missing definition then it is
called instead of any accessors. This causes any model set-up to fail.

As far as I am aware, the accessors for attributes have always been
generated using method_missing (the method missing hook then actually
defines the accessors, so after that method missing is not used).

What might possibly have changed is when this gets triggered. Regardless
if
you do override method_missing it’s a good idea to call to the
superclass
as other aspects of active record may rely on this.

Fred