とりあえずコード書けよ

技術的なことの備忘録。

active_recordのattributeメソッドまとめ

github.com

ちょっと使う機会があったのでまとめ。 変更前後で値がとれるのは便利。

こういうモデルがあったとする。

user = User.first
=> #<User id: 1, firstname: "花子", lastname: "山田", firstname_phonetic: "ハナコ", lastname_phonetic: "ヤマダ", email: "test@example.com">

保存前に使うメソッド

changes_to_save

変更されている値の検知を行う

user.changes
=> {}

user.lastname = "鈴木"
user.lastname_phonetic = "スズキ"
user.changes
=> {"lastname"=>["山田", "鈴木"], "lastname_phonetic" => ["ヤマダ", "スズキ"]}
# { 変更したカラム名のキー => [変更前の値, 変更後の値], ... }

attribute_change_to_be_saved(attr_name)

指定したカラムの変更前後の値を返す

user.attribute_change_to_be_saved("lastname")
=> nil

user.lastname = "鈴木"
user.attribute_change_to_be_saved("lastname")
=> ["山田", "鈴木"]

has_changes_to_save?

変更を検知して true / falseを返す

user.has_changes_to_save?
=> false

user.lastname = "鈴木"
user.lastname_phonetic = "スズキ"
user.has_changes_to_save?
=> true

changed_attribute_names_to_save

変更されるカラム名を配列で返す

user.changed_attribute_names_to_save
=> []

user.lastname = "鈴木"
user.lastname_phonetic = "スズキ"
user.changed_attribute_names_to_save
=> ["lastname", "lastname_phoneic"]
# [変更したカラム名1, 変更したカラム名2]

attributes_in_database

変更される箇所のデータベース上の値を返す

user.attributes_in_database
=> {}

user.lastname = "鈴木"
user.lastname_phonetic = "スズキ"
user.attributes_in_database
=> {"lastname"=>"山田", "lastname_phonetic"=>"ヤマダ"}

attribute_in_database(attr_name)

指定したカラムのデータベース上の値を返す(変更したかどうかは関係なし)

user.attribute_in_database("lastname")
=> "山田"

user.lastname = "鈴木"
user.attribute_in_database(:lastname)
=> "山田"
# 指定はシンボルでも文字列でも可能

will_save_change_to_attribute?(attr_name, **options)

指定したカラムの変更に対して true / falseを返す

user.will_save_change_to_attribute?("lastname")
=> false

user.lastname = "鈴木"
user.will_save_change_to_attribute?("lastname")
=> true

また、オプションとしてfromとtoが使えます。

user.lastname = "鈴木"
# fromは変更前の値が一致した時にtrue
user.will_save_change_to_attribute?("lastname", from: "山田")
=> true

user.will_save_change_to_attribute?("lastname", from: "吉田")
=> false

# toは変更後の値が一致した時にtrue
user.will_save_change_to_attribute?("lastname", to: "鈴木")
=> true

user.will_save_change_to_attribute?("lastname", from: "吉田")
=> false

# fromとtoを同時に渡すと変更前と変更後の値が一致した時にtrue
user.will_save_change_to_attribute?("lastname", from: "山田", to: "鈴木")
=> true

user.will_save_change_to_attribute?("lastname", from: "山田", to: "吉田")
=> false

設定Aから設定Bに変更した時に特定の処理を挟みたいとか、そういう感じの時に使えそうかな? (例は使い方悪いですね・・・笑)

保存後に使うメソッド

saved_change_to_attribute?(attr_name, **options)

指定したカラムが変更されていた場合 true/falseを返す

user.lastname = "鈴木"
user.save
user.saved_change_to_attribute?("lastname")
=> true

こちらもwill_save_change_to_attribute?メソッドと同様にfrom, toオプションが使えます。

saved_change_to_attribute(attr_name)

指定したカラムの変更前後の値を取得する

user.lastname = "鈴木"
user.save
user.saved_change_to_attribute("lastname")
=> ["山田", "鈴木"]
# [変更前の値, 変更した値]

attribute_before_last_save("lastname")

指定したカラムの変更前の値を取得する

user.lastname = "鈴木"
user.save
user.attribute_before_last_save("lastname")
=> "山田"

saved_changes

変更した値を全て取得する

user.lastname = "鈴木"
user.save
user.saved_changes
=> {"lastname"=>["山田", "鈴木"], "updated_at"=>[Mon, 15 Apr 2019 12:36:00 JST +09:00, Thu, 25 Apr 2019 12:26:24 JST +09:00]}
# { カラム名1 => [変更前の値, 変更後の値], カラム名2 => [変更前の値, 変更後の値], ... }

saved_changes?

変更があったら true / falseを返す

user.lastname = "鈴木"
user.save
user.saved_changes?
=> true