0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsで親レコードの際にアソシエーション先の子レードが削除できない場合には削除されないようにする

Posted at

株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら弊社HPからご相談をいただけますと幸いです。
以下のような問題を解決することができます。

  • プロジェクトでRailsエンジニアが足りなくて困っている
  • Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
  • オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら弊社HPからご連絡いただけますと幸いです。

前提

親:子 = 投稿:コメント
という親子関係で、親レコードの作成と一緒に子レコードの作成、親レコードの削除と一緒に子レコードの削除を行いたいということがあります。

その際に、親レコードを削除子レコードが特定の条件の場合には削除できないというバリデーションをつけたいということがあったので、その書き方をメモとして残しておきます。

実装内容

親レコード:Post、子レコード:Comment
という形の構造です。

親レコードであるPostモデルに bofore_destroy でバリデーションをつけます。
この際に、prepend: true オプションを忘れずにつけなければなりません。

prepend: true を指定すると 子レコードを実際に削除する前に、処理を行ってくれるようになります。

app/models/post.rb
  before_destroy :check_delete_post, prepend: true

  private

  def check_delete_post
    ActiveRecord::Base.transaction do
      comments.each do |comment|
        unless comment.destroy
          errors.add(:base, "コメント:#{comment.id}が削除できなかったため、ユーザーを削除できませんでした。")
          raise ActiveRecord::RecordNotDestroyed
        end
      end
    end
  rescue ActiveRecord::RecordNotDestroyed
    throw(:abort)
  end

投稿に紐づくコメントが1つでも削除できないものがあった場合には、ロールバックしてコメントを1件も削除せずにエラーを出すようにします。

app/models/comment.rb
  before_destroy :check_destroy

  private

  def check_destroy
    if status == "published"
      errors.add(:base, "コメントが公開されているため、削除できませんでした。")
      throw(:abort)
    end
  end

参考記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?