Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
60
Help us understand the problem. What is going on with this article?
@ysKey2

RailsのActiveRecordでカラムの変更前後の情報を取得

More than 5 years have passed since last update.

はじめに

ActiveRecordで{attr_name}_wasのメソッドをコールバック時に利用してみたので、せっかくだったらと思い以下のメソッド全部の実行結果をまとめてみる。

  • changed?
  • changed
  • changes
  • {attr_name}_changed?
  • {attr_name}_was
  • {attr_name}_change

※この子だけ使う機会がよく分からないので割愛します!

  • {attr_name}_will_change!

メソッド詳しく知りたい方は以下のリンクからソースコードどうぞ
rails/activemodel/lib/active_model/dirty.rb

目的

以下のコールバック時での各メソッドの実行結果を確認する

  • before_save
  • after_save
  • after_commit

試した内容

色々試すように適当なtestモデル作成

app/models/test.rb
# == Schema Information
#
# Table name: tests
#
#  id                     :integer          not null, primary key
#  score                  :integer          not null
#  grade                  :text(65535)      not null
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#

class Test < ActiveRecord::Base
  before_save  TestCallbacks.new
  after_save   TestCallbacks.new
  after_commit TestCallbacks.new
end

コールバックはあえて分けて用意(理由は特にない
全てのタイミングでbinding.pryを差し込んでみる

app/models/test_callbacks.rb
class TestCallbacks
  def before_save(test)
    binding.pry
  end

  def after_save(test)
    binding.pry
  end

  def after_commit(test)
    binding.pry
  end
end

以下のようなテストデータ用意してgradeカラムを更新

pry(main)> test = Test.first
+----+-------+-------+---------------------------+---------------------------+
| id | score | grade | created_at                | updated_at                |
+----+-------+-------+---------------------------+---------------------------+
| 1  | 80    | C     | 2016-03-03 18:05:55 +0900 | 2016-03-03 18:05:55 +0900 |
+----+-------+-------+---------------------------+---------------------------+
pry(main)> test.update(grade: 'B')

before_saveのタイミングでの結果

[7] pry(#<TestCallbacks>)> test.grade
"B"
[8] pry(#<TestCallbacks>)> test.changed?
true
[9] pry(#<TestCallbacks>)> test.changed
[
    [0] "grade"
]
[10] pry(#<TestCallbacks>)> test.changes
{
    "grade" => [
        [0] "C",
        [1] "B"
    ]
}
[11] pry(#<TestCallbacks>)> test.grade_changed?
true
[12] pry(#<TestCallbacks>)> test.score_changed?
false
[13] pry(#<TestCallbacks>)> test.grade_was
"C"
[14] pry(#<TestCallbacks>)> test.grade_change
[
    [0] "C",
    [1] "B"
]

after_saveのタイミングでの結果

※updated_atカラムが更新されようとしている以外は変わらない

pry(#<TestCallbacks>)> test.grade
"B"
pry(#<TestCallbacks>)> test.changed?
true
pry(#<TestCallbacks>)> test.changed
[
    [0] "grade",
    [1] "updated_at"
]
pry(#<TestCallbacks>)> test.changes
{
         "grade" => [
        [0] "C",
        [1] "B"
    ],
    "updated_at" => [
        [0] Thu, 03 Mar 2016 18:05:55 JST +09:00,
        [1] Thu, 03 Mar 2016 19:03:51 JST +09:00
    ]
}
pry(#<TestCallbacks>)> test.grade_changed?
true
pry(#<TestCallbacks>)> test.score_changed?
false
pry(#<TestCallbacks>)> test.grade_was
"C"
pry(#<TestCallbacks>)> test.grade_change
[
    [0] "C",
    [1] "B"
]

after_commitのタイミングでの結果

pry(#<TestCallbacks>)> test.grade
"B"
pry(#<TestCallbacks>)> test.changed?
false
pry(#<TestCallbacks>)> test.changed
[]
pry(#<TestCallbacks>)> test.changes
{}
pry(#<TestCallbacks>)> test.grade_changed?
false
pry(#<TestCallbacks>)> test.grade_was
"B"
pry(#<TestCallbacks>)> test.grade_change
nil

まとめ

  • {attr_name}_wasのようなメソッドはデータの更新完了後は変更前のデータ取れませんが、after_saveのタイミングであれば変更前のデータ取れるので何かと使えるタイミングが多いんじゃないかなと思いました
  • この辺りのメソッドの面白い活用事例などありましたら教えていただきたいです
    • 特にこの子{attr_name}_will_change!
60
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ysKey2
最近のブームはウクレレ

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
60
Help us understand the problem. What is going on with this article?