yamachan.log

紫陽花

Rails ActiveRecordで値が変更する前後の値を取得する

ActiveRecordで値が変更する前後の値を取得することがあったのでメモ

Rails 2.1あたりからActiveRecordの変更前後の値を取得する機能が備わっている。

method 意味
changed? 変更されているかどうか
changed 変更されているattribute名の配列
changeds 変更されているattribute名と値のハッシュ。値は変更前後の値を配列で。
{attr}_changed? {attr}が変更されているかどうかの判定
{attr}_was {attr}の変更前の値。変更されていない場合は元の値
{attr}_change {attr}の変更前後の値の配列。変更されていなかったらnil
{attr}_will_change! {attr}を変更することを明示。

attrには属性名が入ります。nameの場合 name_wasで変更前の値を取得することができる

使用例

Railsのコールバック処理で複数の配列データを1つに統一したい場合に利用する

コールバック処理

  • before_save
  • before_update
  • after_update

etc...

before_update処理でmerge_tagメソッドを実行する

merge_tagメソッドでは既に登録されていた既存の値(tag)と、

変更が加えられた新規の値tag_wasを組み合わせる(merge)処理が行われ、

self.tagに代入される

before_update :merge_tag

def merge_tag
  # tag_wasには元々のtagの値が入り、
  # mergeの引数のtagは新たなtagの値になる
  self.tag = tag_was.merge(tag)
end

もっと簡単な例で動きを説明すると

tag = Tag.find(1)
#=> #<Tag:0x007fc35ee6fc98 id: 1, name: "ドラえもん", created_at: Wed, 11 Apr 2016 20:21:02 JST +09:00>
tag.name
#=> "ドラえもん"
tag.changed?
#=> false
tag.name = "のび太"
#=> "のび太"
tag.changed?
#=> true
tag.name_was
#=> "ドラえもん"

のように、tag.name_wasで変更前の値を取得することができています。

ActiveRecordのちょっとした機能ですが、応用的な処理を実装する時には便利に使えるかなと思います。