- Published on
Rails 5 モデルの条件付きbefore_destroy
- Authors
- ジャバ・ザ・ハットリ
Rails 5 でモデルに条件付き before_destroy を設定する方法。
例えば Post モデルがあって、レコードを消す前に条件判定をするとする。ステータスがアクティブだったら消さない。アクティブ以外の場合だけレコードを消しても Ok としたい。
そこで以下のようなコードを書いても動かない。
class Post < ApplicationRecord
before_destroy :do_not_destroy_active_post
private
def do_not_destroy_active_post
return false if active?
end
end
どうすればいいのかはここ(Active Record Callbacks)に書いてある。
If the before_validation callback throws :abort, the process will be aborted and ActiveRecord::Base#save will return false. If ActiveRecord::Base#save! is called it will raise an ActiveRecord::RecordInvalid exception. Nothing will be appended to the errors object.
動くコードはこんな感じになる。
class Post < ApplicationRecord
before_destroy :do_not_destroy_active_post
private
def do_not_destroy_active_post
throw(:abort) if active?
end
end
エラーメッセージを加えたければ、throw(:abort)をする前に errors.add すればできる。
ほとんどお約束みたいなことで、現行のプロジェクトを検索してみたらたくさん throw(:abort)が引っかかるが、全てこの条件付き before_destroy だった。私自身の経験としてもこれ以外で throw(:abort)を使ったことが無いのだが。。。
結論としては throw(:abort)したら Ok ってことなんだけど、他の技術ブログで Rails 4からの歴史的経緯とか長々と書いてあって「ググってこういう記事に辿り着いた人ってそんなゴチャゴチャと昔話しまで求めてないのでは」と思ったので簡素に結論だけ書いて終わりにしたい。