Help us understand the problem. What is going on with this article?

Railsのcallbackについて調べた

More than 1 year has passed since last update.

色々詰まったので勉強がてらまとめてみた
Railsのバージョンは3.2

callbackとは

  • オブジェクトの生成・更新・削除のタイミングで呼び出されるメソッド
  • トリガとなるイベント(create, saveなど)の前後に登録可能
  • トリガに対してメソッドを共通化できて便利

callbackの順番

create,update,find,destroyでまとめた
それぞれ上から順番に実行される

create

create_test.rb
hoge = Hoge.new(name: "hoge")
#initialize
after_initialize #newメソッドで生成したときのみ
hoge.save!
#BEGIN TRANSACTION
before_validation
#validation
after_validation
#ROLLBACK
after_rollback   #validationに失敗した時のみ
before_save
around_save
before_create
around_create
#INSERT INTO "hoges"
after_create
after_save
# COMMIT
after_commit

update

update_test.rb
hoge.update(name: "fuga")
#BEGIN TRANSACTION
before_validation
#validation
after_validation
#ROLLBACK
after_rollback   #validationに失敗した時のみ
before_save
around_save
before_update
around_update
#UPDATE "hoges" SET
after_update
after_save
# COMMIT
after_commit

find

find_test.rb
hoge = Hoge.first
# SELECT hoges.* FROM 
#initialize
after_initialize
after_find

destroy

destroy_test.rb
hoge.destroy
#BEGIN TRANSACTION
before_destroy
around_destroy
#DELETE from hoges
after_destroy
# COMMIT
after_commit

changed?が使用できるcallback

要素の変更を確認できるchanged?メソッドが使えるcallbackを調べた。

changed_method.rb
# ここから→
before_validation
after_validation
after_rollback
before_save
around_save
before_update
around_update
after_update
after_save
# →ここまでは使える
after_commit #使えない

changed?系のメソッド一覧

change_series.rb
hoge = Hoge.find_by(name: hoge)
hoge.name  = fuga

#objectが変更されたか?
hoge.changed? #=>true
#指定要素が変更されたか?
hoge.name_changed? #=>true
#指定要素がhogeからfugaに変更されたか?
hoge.name_changed?(from: hoge, to:fuga) #=>true
#指定要素の変更前の値?
hoge.name_was #=>”hoge”
#指定要素の変更前後の値
hoge.name_change #=>[“hoge”, “fuga”]
#変更要素名
hoge.changed #=>[“name”]

accepts_nested_attributes_forを使った時のcallbackの順番

上から順番に処理されます。
ややこしいのであんまり使いたくない。

親:before_validation
子:before_validation
子:after_validation
親:after_validation
親:before_save
親:around_save
親:before_xxx
親:around_xxx
子:before_save
子:around_save
子:before_xxx
子:around_xxx
子:after_xxx
子:after_save
親:after_xxx
親:after_save

around_xxxの使いドコロ

around_xxxの使いドコロがよく分からなかったので調べてみた。
トリガーの前後で処理を定義できるっぽい。便利そう。

around_xxx.rb
def around_save
  # 何かしらの処理
  yield #saves
  # 何かしらの処理2
end
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした