ジャバ・ザ・ハットリ

ベルリンのスタートアップで働くソフトウェアエンジニア

Rails 5 モデルの条件付きbefore_destroy

2017-11-14Rails

Loading...

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ってことなんだけど、他の技術ブログでRails4からの歴史的経緯とか長々と書いてあって「ググってこういう記事に辿り着いた人ってそんなゴチャゴチャと昔話しまで求めてないのでは」と思ったので簡素に結論だけ書いて終わりにしたい。

関連記事


海外移住のQ&Aサイト シティーズ


海外移住向けのQ&Aサイトを運営しています。現在、海外にお住まいの方、これから海外移住や留学、転職をお考えの方はぜひご参加ください。 登録はもちろん無料です。

シティーズ https://www.cityz.jp/

cityz