株式会社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
参考記事