Rails – 更改关联不会将对象标记为脏

编辑 :澄清添加

鉴于以下两个类

class Foo < ActiveRecord::Base belongs_to :bar end class Bar < ActiveRecord::Base end 

当我更改foo上的一个栏时,我想要一种方法来查看foo实例已经改变:

 foo = Foo.find(x) foo.bar # returns # foo.bar = Bar.new foo.changed? # returns false foo.changes # returns an empty hash 

我不想将bar_id设置为脏(因为它没有改变)。拥有以下内容会很好:

 foo.changed? # returns true foo.changes # returns {:bar => [#, nil]} 

是否有一种聪明的方法可以将其破解为Rails? 有没有理由这不是Rails的一部分?

我今天遇到了同样的问题,在通过rails-source运行后,如果我以正确的方式得到你的问题,我找到了一个应该按照你的想法做的解决方法。

转移到您的示例代码应如下所示:

 class Foo < ActiveRecord::Base belongs_to :bar def info bar.info end def info=(val) @changed_attributes[:info] = self.info unless val == self.info self.time_entry.update_attributes! :info => val end end class Bar < ActiveRecord::Base attr_accessible :info end 

这样你就可以调用.changed? 和。改变Foo类的对象。

希望这有助于即使答案有点晚:)

亲切的问候基督徒

顺便说一句。 抱歉英语不好。 我正在努力研究我的ruby技能;)

你使用的是什么版本的Rails? 当我测试它时,它确实报告了。

无论如何,我不确定是否还有可用于belongs_to的后分配回调。 这张https://github.com/rails/rails/issues/586有一张票

如果没有,你可以覆盖assign方法(我之前没试过,但我认为它会起作用:)所以请让我知道)

 class Foo < ActiveRecord::Base belongs_to :bar def bar=(b) bar_id_will_change! unless bar_id == b.id super end end 

更新:再次阅读你的问题,我甚至不确定我是否理解了所有这些问题。 如果它没有改变,你希望它仍然报告真实吗? 即使再次分配同一个对象呢? 在这种情况下,您可以删除unless bar_id == b.id部分

由于Rails 5.1中对@changed_attributes更改,我不得不求助于使用虚拟属性(attr_accessor)来指示检查后更改的关联。 从长远来看,与使用与ActiveRecord::Dirty相关的Rails内部进行混乱相比,这可能会更好