3

编辑:添加了说明

给定以下两个类

class Foo < ActiveRecord::Base
  belongs_to :bar
end

class Bar < ActiveRecord::Base
end

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

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

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

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

有没有一种聪明的方法可以将它破解到 Rails 中?这不是 Rails 的一部分有什么原因吗?

4

3 回答 3

3

我今天遇到了同样的问题,在运行 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? 和 .changes 对 Foo 类的对象。

希望这会有所帮助,即使答案来晚了:)

亲切的问候基督徒

顺便提一句。对不起英语不好。我正在努力研究我的红宝石技能;)

于 2012-10-30T16:16:45.813 回答
2

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

无论如何,我不确定是否可以为 belongs_to 使用 after assign 回调。这个 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零件

于 2012-07-12T21:48:12.060 回答
0

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

于 2018-08-06T07:22:13.023 回答