假设我有两个ActiveRecord模型:LineItem和Article。
class LineItem < ActiveRecord::Base
belongs_to :article
...
end
我在LineItems (Rails 2.3.11)上遇到以下行为:
>> l = LineItem.new
=> #<LineItem id: nil, article_id: nil, ...>
>> l.article_id=10
=> 10
>> l.article
=> #<Article id: 10, ...>
>> l.article_id=20
=> 20
>> l.article
=> #<Article id: 10, ...>
因此,如果article_id已经有一个值,后续的更改不会再改变文章关联。(至少不是立即-只有在保存后设置为新值)
这导致我的验证方法在更新现有的LineItems时出现问题。在我的LineItems-Controller中,我这样更新:
def update
@line_item = LineItem.find(params[:id])
@line_item.attributes = params[:data] #params[:data] contains article_id
...
@line_item.save!
...
end
在我的LineItem类中,我有许多这样的验证(简化):
def validate
if self.article.max_size < self.size
errors.add_to_base("Too big for chosen article.")
end
end
在更新时,此验证作用于"旧"条目,因为新条目仅在self中。Article_id(但不在self.article中)。在上面的条件下,我可以用Article.find(self.article_id)
代替self.article
,但这看起来不像它的本意。
这是一个bug在rails(2.3.11)或我做错了什么?非常感谢。
这不是您遇到的错误,而是AR关联缓存的行为。通过将true
传递给关联方法self.article(true)
,可以在验证过程中强制重新加载关联。
您还可以通过调用#clear_association_cache
来清除LineItem实例的所有缓存关联。
这实际上是一个错误,但它已被修复!(见Alex的评论)