Tatva-Artha

meaning of "it"

ActiveRecord::MissingAttributeError: missing attribute — a bug or a feature?

with 4 comments

Sooner or later, the need arises to assign default values to model attributes. In rails this is usually done in model’s after_initialize() with a new_record? guard.

Something like:

class User
  def after_initialize
    if new_record?
      self.country = "US"
    end
  end
end

This initializes the object with proper default so the UI form gets properly populated and the database gets proper default if user hasn’t overridden it.

Sometimes, you realize that you have (pre-existing?) objects in database that also need the same default if the current value is nil. In such case, you may modify your initializer like this:

class User
  def after_initialize
    self.country ||= "US"
  end
end

This works for both scenarios: User.new and User.find.

However, it introduces a behavior that may not be apparant immediately.

$ script/console
ree> User.find(u.id)
  User Load (0.9ms)   SELECT * FROM `users` WHERE (`users`.`id` = 1) 
ree> User.exists?(:id => u.id)
  RateSearch Load (0.6ms)   SELECT `users`.id FROM `users` WHERE (`users`.`id` = 1) LIMIT 1
ActiveRecord::MissingAttributeError: missing attribute: country
/[prj]/app/models/User.rb:3:in `after_initialize'

A closer look reveals that ActiveRecord tries to be smart and only fetch ‘id’ column when performing Model.exists? call.

Many people have tripped this and logged it as a bug. The report has been silently ignored, and I believe, for good/performance reasons.

So, what do we get around it? Here’s one way.

class User
  def after_initialize
    self.country ||= "US"
  rescue ActiveRecord::MissingAttributeError
    # this should only happen on Model.exists?() call. It can be safely ignored.
  end
end

As they say, it is not a bug, it is a feature.

http://www.tatvartha.com/wp-content/plugins/sociofluid/images/digg_16.png http://www.tatvartha.com/wp-content/plugins/sociofluid/images/reddit_16.png http://www.tatvartha.com/wp-content/plugins/sociofluid/images/stumbleupon_16.png http://www.tatvartha.com/wp-content/plugins/sociofluid/images/delicious_16.png http://www.tatvartha.com/wp-content/plugins/sociofluid/images/google_16.png http://www.tatvartha.com/wp-content/plugins/sociofluid/images/twitter_16.png

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

Written by Sharad

March 3rd, 2011 at 8:07 pm

Posted in All,Technology

Tagged with , ,

4 Responses to 'ActiveRecord::MissingAttributeError: missing attribute — a bug or a feature?'

Subscribe to comments with RSS

  1. Thanks for the help. In the latest rails release the exception has been moved to the ActiveModel class though.

    ActiveModel::MissingAttributeError

    Ryan

    11 Apr 11 at 11:46 pm

  2. I think you mean ActiveModel::MissingAttributeError – ActiveRecord::MissingAttributeError isn’t defined.

    Jason

    12 Feb 12 at 8:14 pm

  3. Bug or feature, it still doesn’t follow the priniciple of least surprise. What a gotcha, at least the first time you experience it!

    Nathan

    8 Nov 12 at 11:28 am

  4. This should be done with an if statement check on the presence of attributes["country"] since catching the exception in this case will be relatively slow if you are generating thousands of objects. See: http://www.simonecarletti.com/blog/2010/01/how-slow-are-ruby-exceptions/

    Nathan woodhull

    14 Nov 12 at 12:35 pm

Leave a Reply