部署之后发生ActiveModel :: MissingAttributeError,然后在一段时间后消失
我有一个Rails 3.0.9的应用程序,一旦部署,遭受了一堆的ActiveModel :: MissingAttributeErrors,出现造成500s。 错误发生的相当随机,有时一个页面将加载,其他时间不会,但属性是数据库中的所有现有属性,应该find。
奇怪的是,过了一段时间,错误消失了。 突然之间,他们停止引发一个问题。
我已经search了一个解决scheme,但是这个错误大多发生在有人完成Model.all(:select => 'column_x,column_y')
并且正在调用column_z
或者他们正在使用cache_money时。 我没有做这些事情。
谁能帮忙?
你可能有一个查询不会返回所有的列(即使用:select
),然后cache_money; 或者其他一些ActiveRecord插件使用after_initialize
callbackafter_initialize
,该函数在创build新的ActiveRecord对象时执行(即从数据库中提取时)。
在初始化callback中,有些东西试图访问或使用未包含在:select
的属性。 你会期望这个返回nil的那个属性,但是会抛出一个ActiveRecord :: MissingAttributeError。
你可以像文章中所build议的那样救援ActiveRecord :: MissingAttributeError,或者在插件尝试访问或修改属性之前修改插件以使用has_attribute?(:attribute_name)
。
如果您在更新数据库后没有进行任何部署或服务器重新启动,直接遇到此问题,那么对我有效的方法可能适用于您:
运行heroku restart
,它应该被修复。 在dyno重新启动之前,旧数据有时会保留在服务器上,所以再次启动它将清除所有数据,并防止这种错误。 希望这可以帮助。
我发现一个有趣的事情导致了相同的错误。 为了重用代码,我们将一个演示者类与一个演示者类进行子分类,演示者将执行分组以在图视图中使用。
为了简化,它是这样的:
class PostPresenter def query Post.where(...stuff....).includes(:wombat) end end
这个聚合器做了如下的事情来build立一个每天post的表格:
class AggregatePostPresenter < PostPresenter def group_query query.select('count(*) as cnt, date(created_at)').group('date(created_at)') end end
对“group_query”的调用导致了一个ActiveModel :: MissingAttributeError,因为我认为“包含”Wombat的尝试失败了,因为“wombat_id”不在“select”中包含的属性中。
但是,这可能不是您的答案,因为无论是否启用caching,都会发生这种情况。
我遇到过这个问题。 确保您的select:
包括视图中引用的所有字段, 包括您的方法中调用的任何关系ID和任何属性。
当你的观点和关系很复杂时,缺less的属性就很难确定。 debugging这个最简单的方法是删除where
子句的select
部分,看看查询/范围/方法是否正确运行。 如果是这样,那么将所有属性添加到select
并一次删除不需要的属性,直到find违规属性。
当我尝试使Ajax(实际上是angularjs)调用来填充就地编辑select字段时,类似的问题令我恼火。
我只想要一个id和名称属性to_json,并不断得到MissingAttributeError。
通过在用于主索引的模型中使用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
似乎在工作。 我正在亲自抨击它,但是我发现了一个很好的解释。
我通过将.to_json
添加到我的控制器渲染结束来解决此问题。
你需要添加行
rescue ActiveRecord::MissingAttributeError
在模型的after_initialize()方法中