💬

ActiveRecord の #changes_to_save と #saved_changes

に公開

最近、よく使っているので ActiveRecord::Base#changes_to_save#saved_changes の紹介。
名前の通りではあるんですがそれぞれ

  • #changes_to_save => 保存前の変更内容
  • #saved_changes => 保存後の変更内容

のような情報を取得することができます。

user = User.find_by(name: "homu")
pp user
# => #<User:0x000076769d6d3348 id: 1, name: "homu", email: nil, age: 14>

# レコードを取得した直後はどちらも空
pp user.changes_to_save # => {}
pp user.saved_changes   # => {}

# レコードの内容を変更し、保存される前
# このときの変更内容は #changes_to_save で情報が取得できる
user.assign_attributes(name: "mami", email: "mami@example.com")
pp user.changes_to_save # => {"name" => ["homu", "mami"], "email" => [nil, "mami@example.com"]}
pp user.saved_changes   # => {}

# レコードの内容を変更し、保存した後
# このときの保存された値は #saved_changes で情報が取得できる
user.save!
pp user.changes_to_save # => {}
pp user.saved_changes   # => {"name" => ["homu", "mami"], "email" => [nil, "mami@example.com"]}

コールバックとかで保存前、保存後の状態をゴニョゴニョしたいときに便利ですね。
ちなみに似たようなメソッドで #changes もあるんですがこちらは #changes_to_save と同じような挙動になります。

vser = User.find_by(name: "homu")
pp user
# => #<User:0x000076769d6d3348 id: 1, name: "homu", email: nil, age: 14>

user.assign_attributes(name: "mami", email: "mami@example.com")
pp user.changes         # => {"name" => ["homu", "mami"], "email" => [nil, "mami@example.com"]}
pp user.changes_to_save # => {"name" => ["homu", "mami"], "email" => [nil, "mami@example.com"]}
pp user.saved_changes   # => {}

user.save!
pp user.changes         # => {}
pp user.changes_to_save # => {}
pp user.saved_changes   # => {"name" => ["homu", "mami"], "email" => [nil, "mami@example.com"]}

関連

GitHubで編集を提案

Discussion