58

I have a Rails 3.0.9 app that, once it is deployed, suffers from a bunch of ActiveModel::MissingAttributeErrors that crop up causing 500s. The errors occur fairly randomly, sometimes a page will load, other times it won't, but the attributes are all existing attributes in the database and should be found.

The strange part is that after a while, the errors go away. Suddenly, they stop causing an issue.

I have searched about for a solution to this, but this error mostly occurs either when someone has done Model.all(:select => 'column_x,column_y') and are calling for column_z or when they are using cache_money. I am doing neither of these things.

Can anyone help?

philnash
  • 70,667
  • 10
  • 60
  • 88

7 Answers7

157

You probably have a query that doesn't return all the columns (i.e. uses :select) and then cache_money; or some other ActiveRecord plugin uses an after_initialize callback, which executes whenever a new ActiveRecord object is created (i.e. when fetched from the database).

In that initialize callback, something tries to access or use an attribute that wasn't included in the :select. You'd expect this to return nil for that attribute, but an ActiveRecord::MissingAttributeError is thrown instead.

You can rescue ActiveRecord::MissingAttributeError like the article suggests, or patch the plugin(s) to use has_attribute?(:attribute_name) before they try to access or modify the attribute.

peak
  • 105,803
  • 17
  • 152
  • 177
randomguy
  • 12,042
  • 16
  • 71
  • 101
  • 1
    Thanks, but that doesn't seem to be the case. I don't have any caching or queries that don't return all the columns. – philnash Jul 27 '11 at 16:50
  • Oh, sorry I miss read your original question. Please describe the errors you are getting more accurately, ie. provide the log file output. It should tip off which attribute/column in which model is giving the ActiveModel::MissingAttributeError. – randomguy Jul 27 '11 at 16:54
  • 29
    +1 This may not have solved OP's question, but it is exactly the issue I was facing. – Nathan Nov 08 '12 at 17:22
  • Using `has_attribute?` worked for me in Rails 4, but I'm still not sure why. I'm having the same issue happening in test, and I get that error when using `try`. Calling `has_attribute?` before I call that attribute getter makes the problem disappear. – Ten Bitcomb Mar 22 '16 at 22:30
  • Don't forget scopes and default scopes. – vzamanillo Jan 24 '19 at 18:59
7

If you have been having this issue only directly after updating your database without any deploys or server restarts following, then what worked for me may work for you:

Run heroku restart and it should be fixed. Before the dyno restarts old data sometimes remains cached on the server, so starting it up again will scrub all of that data and prevent it from causing errors of that sort. Hope this helps.

rmtsukuru
  • 88
  • 2
  • 7
4

I encountered this issue. Make sure your select: includes all fields referenced in your view, including any relationship IDs and any attributes called within your methods.

The missing attribute can be difficult to identify whenever your views and relationships are complex. The easiest way to debug this is to remove the select portion of your where clause and see if the query/scope/method runs correctly. If so, then add all of the attributes to the select and remove unneeded attributes one-at-a-time until you find the offending attribute.

scarver2
  • 7,887
  • 2
  • 53
  • 61
3

I found an interesting take on this that resulted in the same error. In an attempt to reuse code we subclasses a presenters class with a presenters class that performed grouping to use in a graph view.

To simplify, it was something like:

class PostPresenter 
  def query
    Post.where(...stuff....).includes(:wombat)
  end
end

The the aggregator did something like the following to build a table of posts per day:

class AggregatePostPresenter < PostPresenter
  def group_query
    query.select('count(*) as cnt, date(created_at)').group('date(created_at)')
  end
end

A call to "group_query" results in an ActiveModel::MissingAttributeError since, I think, the attempt to "includes" Wombat fails because "wombat_id" wasn't in the attributes included in the "select".

This is probably not your answer, however, since it happens regardless of whether or not cache is enabled.

GSP
  • 3,763
  • 3
  • 32
  • 54
1

A similar problem was annoying me when I was trying to make Ajax (actually angularjs) calls to populate an edit-in-place select fields.

I just wanted an id and name attributes to_json and kept getting the MissingAttributeError.

Realised I gotcha'd myself by having an as_json method in the model which is used for the main index and show calls on the model. Basically it was the as_json that was not seeing the attributes it expected.

@foo=Foo.select("id,name")

respond_to do |format|
    format.json  { render :json => @foo.to_json }      
end

gave the error but

respond_to do |format|
    format.json  { render :json => { :foo=>@foo.as_json(:only=>[:id,:name]) } }     
end

seems to be working. I was close to sussing it myself but I found a great explanation at.

http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/

blythburgh
  • 93
  • 5
1

I fixed this by adding .to_json to the end of my controller render.

Robbie Guilfoyle
  • 3,363
  • 1
  • 18
  • 18
-9

you need to add line

rescue ActiveRecord::MissingAttributeError 

in your after_initialize() method of the model

kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • 2
    Better to use has_attribute?(:attr_name) in the method run by after_initialize, rather than actually hit the error in the first place – nonrectangular Apr 30 '15 at 18:19