【Rails】skip_callbackとset_callback
先日ちょっとはまった現象についてのメモ
(いやといっても修整ミスなんだけどね・・)
とあるモデルでの話。
- saveするときにcallback処理を走らせたい
- どうしてもsaveを2回走らせたい
というケースがあって、
最初、
class Hoge < ActiveRecord::Base after_save :fuga def piyo hoge = Hoge.new ## #初期保存 hoge.save ## #追加処理 hoge.save end def fuga p "yukkurisiteittene" end end
と書いてたんだけど、これだと当然save時に2回のcallbackが走る。
callbackは1回で良かったので、とりあえず、
class Hoge < ActiveRecord::Base after_save :fuga def piyo hoge = Hoge.new ## #初期保存 Hoge.skip_callback(:save, :after, :fuga) hoge.save Hoge.set_callback(:save, :after, :fuga) ## #追加処理 hoge.save end def fuga p "yukkurisiteittene" end end
としてみた。
でもHogeモデルは他からも操作されるのと、updateが走ったときはcallback処理したくなかったので、
after_saveじゃなくてafter_createでいいじゃんwと、
class Hoge < ActiveRecord::Base after_create :fuga def piyo hoge = Hoge.new ## #初期保存 Hoge.skip_callback(:save, :after, :fuga) hoge.save Hoge.set_callback(:save, :after, :fuga) ## #追加処理 hoge.save end def fuga p "yukkurisiteittene" end end
単純にこうしてみたところ、
callbackが2回走った。。(´;ω;`)
その時はafter_createしか仕込んでいないのになぜ2回走ったのかすぐわからず。。
(でもこうやって書いてみるとすぐわかるなぁ。。)
この理由は、
- 1回目のsaveの前のHoge.skip_callback(:save, :after, :fuga)はそもそもきかない。(after_createなので)
- ので、通常通りafter_createが走る。
- 1回目のsaveの後のHoge.set_callback(:save, :after, :fuga)でafter_save :fugaがHogeモデルに追加されてしまっている。
- 2回目のsaveの時にHoge.set_callback(:save, :after, :fuga)で追加されたcallbackが走る。
という感じ。
そんなこんなで2回callbackが走ったと。
なのでこの場合、1回目のsaveはcreate、2回目のsaveはupdateなので、skip_callbackなどはいらなくて、
class Hoge < ActiveRecord::Base after_create :fuga def piyo hoge = Hoge.new ## #初期保存 hoge.save ## #追加処理 hoge.save end def fuga p "yukkurisiteittene" end end
これでおkw
簡単じゃねーかΣ(゚д゚lll)
こうなんというか、モデルが大きくなって、汎用部分を切りだして親にincludeしだしたり、callbackが多くなってきたりすると、単純なミスもすぐ気づかない。。という(´・ω・`;)
特にcallbackは注意しないと危険ですね。
通常通りbefore_saveとかでフックするのもあるし、
observerでフックするのもあるし、
プラグインがフックするのもあるし。。。
ちゃんと注意しなきゃならんなと・・
というか整理しなきゃならんなと、、改めてオモタ(´・ω・`)
初ブログ
これからちょいちょい更新していこうと思います(´・ω・`)