skip_callbackとset_callbackを用いて一時的にコールバックを回避しようとしたらset_callbackがうまくいかなかった。その時の状況と回避策を記録。
やりたいこと
こちらのコールバックを一時的にスキップしたい。
before_validation :func, on: :action
最初にやったこと
skip_callback
、set_callback
を用いて実装した。
skip_callback(:validation, :before, :func)
------------------------------------------
# 処理を実行
------------------------------------------
set_callback(:validation, :before, :func)
しかし、このあと他の動作に不具合が出てしまい、原因を調査した。
skip_callback、set_callbackとは
skip_callback
は設定されているコールバックをスキップさせることができる。ただし、一度実行するとずっとskipしたままになってしまうため、set_callback
を用いて戻す必要がある。
うまくいかない原因
on: :action
の再設定ができていないため。
つまり、以下のようにコールバックの設定が変わってしまっていたため、挙動が変わってしまった。
# スキップ前
before_validation :func, on: :action
# スキップ後
before_validation :func
対処
最初に行ったset_callback
は、on: :action
に関して特に指定をしていない。
set_callback(:validation, :before, :func)
set_callbackでは、on: action
の設定をしておらず、on: action
の設定が無くなってしまっていた。
on: :action
の設定をしなければいけないため、onで設定している場合はその設定も引数に入れなければならないらしい。
set_callback(:validation, :before, :func, on: :action)
しかし、こちらをやってみても改善されず。
ソースコードにコメントしてある引数にはif
, unless
, prepend
しか無いためon: :action
の設定は難しそう。
最終的な対処法としては、コールバックを回避して処理を行うメソッドが存在するため、こちらを用いることにした。
https://railsguides.jp/active_record_callbacks.html#%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%82%92%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97%E3%81%99%E3%82%8B
まとめ
skip_callback
、set_callback
はコールバックを回避するための便利なメソッドですが、on
を用いた条件付けがされている場合かつ全てのコールバックを回避しても問題ない場合はそもそもコールバックを回避できるメソッドを使った方が良いのかなと今のところ考えています。