通过 _id 属性更新 AR 关联不会更新关联对象(验证之前)
假设我有两个 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_id 中) self.article)此时。我可以在上面的情况下将 self.article
替换为 Article.find(self.article_id)
,但这看起来并不像它应该的那样。
这是 Rails (2.3.11) 中的错误还是我做错了什么?多谢。
Let's say I have two ActiveRecord models: LineItem and Article.
class LineItem < ActiveRecord::Base
belongs_to :article
...
end
I'm experiencing the following behaviour on 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, ...>
So if article_id already has a value, a subsequent change doesn't change the article association anymore. (At least not immediately - only after save it has been set to the new value.)
This is causing me problems in my validate method when updating existing LineItems. In my LineItems-Controller I do update like this:
def update
@line_item = LineItem.find(params[:id])
@line_item.attributes = params[:data] #params[:data] contains article_id
...
@line_item.save!
...
end
In my LineItem class I have many validations like this (simplified):
def validate
if self.article.max_size < self.size
errors.add_to_base("Too big for chosen article.")
end
end
On updates this validation acts on the 'old' article since the new one is only in self.article_id (but not in self.article) at this point. I could replace self.article
with Article.find(self.article_id)
in the condition above but this doesn't look like the way it's meant to be.
Is this a bug in rails (2.3.11) or am I doing something wrong? Thanks a lot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这不是您遇到的错误,而是 AR 关联缓存的行为。您可以通过将
true
传递给关联方法:self.article(true)
,强制在验证期间重新加载关联。您还可以通过调用
#clear_association_cache
清除 LineItem 实例的所有缓存关联。更新:
这实际上是一个错误,但已被修复! (参见亚历克斯的评论)
It is not a bug you are encountering, but rather the behaviour of the AR association cache. You can force the association to be reloaded during validation by passing
true
to the associtaion method:self.article(true)
.You could also clear all cached assocations for a LineItem instance by calling
#clear_association_cache
.UPDATE:
It actually was a bug, but it has been fixed! (See Alex's comment)