Ruby on rails 通过"id属性"更新AR关联不';t更新关联对象(验证前)

Ruby on rails 通过"id属性"更新AR关联不';t更新关联对象(验证前),ruby-on-rails,validation,activerecord,associations,updating,Ruby On Rails,Validation,Activerecord,Associations,Updating,假设我有两个ActiveRecord模型:LineItem和Article class LineItem < ActiveRecord::Base belongs_to :article ... end 在我的LineItem类中,我有许多这样的验证(简化): def验证 如果self.article.max_size

假设我有两个ActiveRecord模型:LineItem和Article

class LineItem < ActiveRecord::Base
  belongs_to :article
  ...
end
在我的LineItem类中,我有许多这样的验证(简化):

def验证
如果self.article.max_size
更新时,此验证作用于“旧”文章,因为此时新文章仅在self.article_id中(但不在self.article中)。在上述情况下,我可以将
self.article
替换为
article.find(self.article\u id)
,但这看起来不像它的本意


这是rails(2.3.11)中的错误还是我做错了什么?非常感谢。

这不是您遇到的错误,而是AR关联缓存的行为。通过将
true
传递给associtaion方法:
self.article(true)
,可以在验证期间强制重新加载关联

您还可以通过调用
#clear_association_cache
清除LineItem实例的所有缓存关联

更新:


它实际上是一个bug,但它已经被修复了!(参见Alex的评论)

谢谢,这就成功了。备注:虽然将true传递给关联始终有效,
self.clear\u association\u cache
在上面的irb示例中不起作用,因为它不作用于新的(未保存的)记录。但是在Pre_验证回调中使用它通常是可以的。这实际上是一个bug,一个非常可怕的bug,它在互联网上造成了各种各样的破坏。它在3.1或3.2中是固定的,但我经常在3.0和一些早期版本中遇到它。如果在更改_id之前引用了关联(在模型过滤器中并不少见),则关联不会更改。
>> 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, ...>
def update
  @line_item = LineItem.find(params[:id])
  @line_item.attributes = params[:data] #params[:data] contains article_id
  ...      
  @line_item.save!
  ...
end
def validate
  if self.article.max_size < self.size
    errors.add_to_base("Too big for chosen article.")
  end
end