部署后出现ActiveModel :: MissingAttributeError错误,一段时间后错误消失。

58
我有一个Rails 3.0.9应用程序,一旦它被部署,就会出现大量的ActiveModel :: MissingAttributeErrors,导致500错误。这些错误有时候会随机出现,有时候页面可以正常加载,有时候不行,但是这些属性都是数据库中已存在的属性,应该能够找到。
奇怪的是,在一段时间后,这些错误会消失。突然之间,它们不再成为问题。
我已经搜索了解决方法,但是这个错误通常发生在某人执行“Model.all(:select =>'column_x,column_y')”并调用“column_z”或者使用cache_money时。 我没有做任何这些事情。
有人可以帮忙吗?
8个回答

157

你可能有一个查询并不返回所有列(即使用:select),然后使用cache_money;或者其他ActiveRecord插件使用after_initialize回调,它会在创建新的ActiveRecord对象时执行(即从数据库中获取时)。

在该初始化回调中,某些内容尝试访问或使用没有包含在:select中的属性。你期望这将返回该属性的nil值,但实际上会抛出ActiveRecord::MissingAttributeError异常。

你可以像文章建议的那样拯救ActiveRecord::MissingAttributeError,或者修补插件以在尝试访问或修改属性之前使用has_attribute?(:attribute_name)


1
谢谢,但看起来不是这种情况。我没有任何缓存或查询不返回所有列的问题。 - philnash
哦,抱歉我误读了你的原始问题。请更准确地描述您遇到的错误,即提供日志文件输出。它应该会提示是哪个模型中的哪个属性/列导致了ActiveModel :: MissingAttributeError。 - randomguy
29
这可能没有解决原作者的问题,但却恰好是我所遇到的问题。 - Nathan
在Rails 4中,使用has_attribute?对我很有用,但我仍然不确定为什么。我在测试中遇到了同样的问题,并且在使用try时会出现错误。在调用属性getter之前调用has_attribute?可以解决这个问题。 - Ten Bitcomb
不要忘记作用域和默认作用域。 - vzamanillo

7
如果您在更新数据库后直接出现此问题,而没有进行部署或服务器重新启动,则我所使用的方法可能适用于您:运行heroku restart,问题就会得到解决。在重启动力之前,旧数据有时会保留在服务器缓存中,因此再次启动它将清除所有这些数据,并防止其导致该类错误。希望这可以帮助您。

4
我遇到了这个问题。请确保您的select:包括视图中引用的所有字段,包括任何关系ID和在方法中调用的任何属性。
每当您的视图和关系复杂时,缺少的属性可能很难识别。调试的最简单方法是删除where子句中的select部分,查看查询/作用域/方法是否正确运行。如果是这样,请将所有属性添加到select中,并逐个删除不需要的属性,直到找到有问题的属性。

3
我找到了一个有趣的观点,它导致了相同的错误。为了重复使用代码,我们将一个执行分组操作以用于图表视图的Presenter类子类化为另一个Presenter类。
简单来说,就是像这样的东西:
class PostPresenter 
  def query
    Post.where(...stuff....).includes(:wombat)
  end
end

聚合器执行以下操作来构建每天帖子数量的表格:
class AggregatePostPresenter < PostPresenter
  def group_query
    query.select('count(*) as cnt, date(created_at)').group('date(created_at)')
  end
end

调用 "group_query" 会导致 ActiveModel::MissingAttributeError 错误,我认为是因为尝试 "includes" Wombat 失败,因为 "wombat_id" 没有包含在 "select" 中的属性中。

然而,这可能不是您要找的答案,因为它发生的情况与缓存是否启用无关。


1
我通过在控制器渲染末尾添加 .to_json 来解决了这个问题。

1
我很感兴趣。这是怎样解决问题的? - johnsyweb

1
当我试图使用Ajax(实际上是angularjs)调用来填充可编辑选择字段时,遇到了类似的问题。我只想要一个id和name属性to_json,却一直收到MissingAttributeError错误。
后来我意识到,在模型中有一个用于主索引和显示调用的as_json方法,这个方法导致了as_json无法看到它所期望的属性。基本上,这就是as_json没有看到它所期望的属性。
@foo=Foo.select("id,name")

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

给出了错误,但是

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

似乎正在运作。我差点自己就搞定了,但在那里找到了一份很好的解释。

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


0
(不针对问题描述,而是针对错误标题)
这可能对仍然遇到“缺少属性”错误的人有所帮助。
我在没有从数据库加载属性时遇到了这个错误。
user = User.where(some_criteria).only(:id, :first_name).first
user.last_name # throws missing attribute error because it wasn't loaded in `only` method

你可能只加载了某个存储中的选择属性,确保你获取了所需的字段。

-9

你需要添加一行

rescue ActiveRecord::MissingAttributeError 

在你的模型的after_initialize()方法中。

2
最好在由after_initialize运行的方法中使用has_attribute?(:attr_name),而不是首先触发错误。 - nonrectangular

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接