在rails中的ActiveRecord对象中跟踪脏的非持久属性

San*_*ino 26 activerecord activemodel ruby-on-rails-3

我有一个从ActiveRecord继承的对象,但它有一个不在DB中持久化的属性,如:

 class Foo < ActiveRecord::Base
   attr_accessor :bar
 end
Run Code Online (Sandbox Code Playgroud)

我希望能够使用ActiveModel Dirty提供的'bar_changed?'等方法跟踪'bar'的更改.问题是,当我尝试在此对象上实现Dirty时,如文档中所述,我收到错误,因为ActiveRecord和ActiveModel都定义了define_attribute_methods,但是参数数量不同,所以我在尝试时遇到错误调用define_attribute_methods [:bar].

define_attribute_methods在包括之前尝试了别名ActiveModel::Dirty,但没有运气:我得到一个未定义的方法错误.

关于如何处理这个问题的任何想法?当然我可以手动编写所需的方法,但我想知道是否可以使用Rails模块,通过将ActiveModel功能扩展到ActiveRecord未处理的属性.

Ale*_*dro 41

我正在使用这种attribute_will_change!方法,似乎工作正常.

它是一个定义的私有方法active_model/dirty.rb,但ActiveRecord将它混合在所有模型中.

这是我最终在我的模型类中实现的:

def bar
  @bar ||= init_bar
end
def bar=(value)
  attribute_will_change!('bar') if bar != value
  @bar = value
end
def bar_changed?
  changed.include?('bar')
end
Run Code Online (Sandbox Code Playgroud)

init_bar方法仅用于初始化属性.您可能需要也可能不需要它.

我不需要指定任何其他方法(例如define_attribute_methods)或包含任何模块.您必须自己重新实现一些方法,但至少行为将与ActiveModel大致一致.

我承认我还没有彻底测试过,但到目前为止我没有遇到任何问题.