class Hoge
include ActiveModel::Model
include ActiveModel::Dirty
def self.attributes
[ :name, :address, :tel, :note ]
end
attr_accessor *self.attributes
define_attribute_methods *self.attributes
def initialize(args)
args.each do |k,v|
raise "unpermitted args:#{k}" unless self.class.attributes.index(k)
self.send("#{k}=", v)
end
# 要素の変更検知
self.class.attributes.each do |attribute_name|
define_singleton_method("#{attribute_name}=") do |value|
# self.class.send(:define_method, "#{attribute_name}=")でもOK
self.send("#{attribute_name}_will_change!") unless value==self.send(attribute_name)
super(value)
end
end
end
end
使用例
# 初期化
> hoge = Hoge.new(name: 'yamada', tel: '090512221234')
=> #<Hoge:0x007f8f3b093b58 @name="yamada", @tel="090512221234">
# 変更なしとなることを確認
> hoge.changed?
=> false
> hoge.changes
=> {}
# 変更してみる
> hoge.tel = "08013456789"
=> "08013456789"
# 変更が検知される
> hoge.changed?
=> true
# 差分もバッチリ
> hoge.changes
=> {"tel"=>["090512221234", "08013456789"]}