通过 _id 属性更新 AR 关联不会更新关联对象(验证之前)

发布于 2024-12-03 08:50:53 字数 1235 浏览 8 评论 0原文

假设我有两个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花落人断肠 2024-12-10 08:50:53

这不是您遇到的错误,而是 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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文