Edited at

ActiveModel::Dirtyのメソッドを使って変更を感知しよう

More than 5 years have passed since last update.

ActiveRecordを使っていると時々プログラム内でModelオブジェクトの値を変更してから、変更前の値が欲しくなったりすることがある。

そんなときはActiveModel::Dirtyのメソッドを使うとModelのオブジェクトに変更があった時に変更の情報を取得出来る。

# たとえばUserのレコードを一個引っ張ってきて

u = User.last
=> #<User id: 5, age: 19, name: "Kiriko Takemura">

# 変更されていないことが確認出来る
u.changes
=> {}

u.changed
=> []

u.changed?
=> false

# 名前を変更してみる
u.name = "Caroline Charonplop Kyary Pamyu Pamyu"

# するとchangesが変更されたプロパティの変更前と変更後のデータが取得できる。
u.changes
=> {"name"=>["Kiriko Takemura", "Caroline Charonplop Kyary Pamyu Pamyu"]}

# booleanでも取得できる
u.changed?
=> true

# 変更されたプロパティ名だけ取得もできる
u.changed
=> ["name"]

# と言うことは、何回も変更したら変更するだけ履歴として残る?
u.name = "Kyary Pamyu Pamyu"

# 残念。そんなことはなく変更前と最新のデータだけ取得出来る。
u.changes
=> {"name"=>["Kiriko Takemura", "Kyary Pamyu Pamyu"]}

# 違うプロパティも変更してみる
u.mail = "kyary@pamyupamyu.com"
=> "kyary@pamyupamyu.com"

# ちゃんと変更したプロパティを取得できる
u.changed
=> ["name", "mail"]

# こんな感じでいくつ変更しても残る
u.age = 20
u.changed
=> ["name", "mail", "age"]

こういうメソッドがあると変更前の情報を後で使いたいときにいちいち別に一時的な変数を用意して取っておくなんてことをしなくても済む。

今更だけど題名は「感知」じゃなくて「検知」にすべき気だったがしてきた。