箱のプログラミング日記。

渋谷の自社開発企業でRails書いてます。

new_record?とかchanged?とかRailsの便利なメソッドまとめ

f:id:y_hakoiri:20191102134313j:plain

データベースとのやりとりで非常に便利なメソッドをいくつか使用する機会がありとてもRailsらしくて感動したので、いくつかまとめておきます。

新しいオブジェクトかどうか【new_record?】

その名の通り、オブジェクトが新しいレコードかどうかを検証してくれるものです。返り値は真偽値。

@user.new_record?
=> true

新規作成/編集でビューの出し分けをしたい時とかに使えますね。

オブジェクトが変更されたかどうか【changed?】

こちらもメソッド名から想像がつく通り、オブジェクトの内容が変更されたかどうかを検証してくれます。こちらも返り値は真偽値。

@user.changed?
=> true

ただこのchangedですがRails5.1以降非推奨になったらしく、今は代替としてhas_changes_to_save?とsaved_changes?が用意されています。

@user.has_changes_to_save?
=> true

has_changes_to_save?は文脈から想像できる通り、updateされる前、つまりafter_updateよりも前に「このオブジェクトがこれから変更される予定かどうか」を検証してくれるもの。

バリデーションのコールバックとかで使えそう。

@user.saved_changes?
=> true

こちらは完全に保存された後に検証ができる。

こちらは更新後のリダイレクト処理と一緒に使ったりすることができそう。

タイミングによって使い分け注意ですね。

特定のカラムが変更されたかどうか

「ユーザーのメールアドレスが変更されたかどうかを確認したい」といったように、特定のカラムの値だけを検証したい場合

(更新前)

@user.will_save_change_to_name?
=> false

@user.will_save_change_to_email?
=> true

(更新後)

@user.saved_change_to_name?
=> false

@user.saved_change_to_email?
=> true

こちらもupdate前と後で記述が異なりますが、「will_save」なのか「saved」なのかの違いのみ。簡単。

更新前のデーターベースの値を取得

またupdateしていない段階で「これから変更される内容じゃなくて、もともと今データベースに保存されている値を取得したいんだ!!」みたいなことってありますよね。あるはず。

@user.email
=> "hogehoge.updated@gmail.com"

@user.email_in_databese
=> "hogehoge@gmail.com"

たとえデータベースに保存されていないとしても、assign_attributeとかでsaveはしていないけど更新した状態のオブジェクトを参照すると、更新後の値を取得することになる。

現状データベースに保存されている、つまり変更前の値を取得したい場合はカラム_in_databaseで解決。

これもとても直感的で分かりやすいですね。

参考

Rails 5.1 で attribute_was, attribute_change, attribute_changed?, changed?, changed 等が DEPRECATION WARNING - Qiita

ActiveRecordの変更有無や変更前後の値 | lambda consulting