

postモデルのレコードを削除した際に、それに紐づくcommentモデルのレコードを削除したいのですが、以下のエラーになります。  
現状コメントがなければ正常に削除ができる状態です。

わかる方がいましたらよろしくお願いします。

**エラーメッセージ:**

[code]

    Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`anipho_development`.`comments`, CONSTRAINT `fk_rails_2fd19c0db7` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`))
    
[/code]

現状のコードはこんな感じです

マイグレーションファイル

[code]

    class CreateComments < ActiveRecord::Migration[6.0]
      def change
        create_table :comments do |t|
          t.references :user, foreign_key: true
          t.references :post, foreign_key: true
          t.string     :content, null: false
          t.timestamps
        end
      end
    end
    
[/code]

comment.rb

[code]

    class Comment < ApplicationRecord
      belongs_to :user
      belongs_to :post
      validates :content, presence: true
    end
    
[/code]

post.rb

[code]

    class Post < ApplicationRecord
      extend ActiveHash::Associations::ActiveRecordExtensions
      belongs_to_active_hash :category
      belongs_to :user
      has_one_attached :image
      has_many :comments, dependent: :destroy
    
      with_options presence: true do
       validates :image
       validates :title
       validates :category_id, numericality: { other_than: 1 , message: "は--以外から選んでください"} 
      end
    end
    
[/code]

user.rb

[code]

    class User < ApplicationRecord
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :validatable
    
      has_many :posts
      has_many :comments
      
      PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i.freeze
      validates :nickname, presence: true
      validates :password, format: { with: PASSWORD_REGEX}
      
    end
    
[/code]


CC BY-SA 4.0
2021-01-20T04:52:57.720
73428
2023-11-07T01:08:40.933
2021-01-20T11:50:41.707
3060
43597
question
ruby-on-rails mysql
外部キーを持つデータのdestroyがうまくいかず、dependentオプションを付けてもエラーになってしまいます。


見た感じちゃんと動きそうなコードですね。。  
postモデルの削除はどうやって行っていますか？

レコードの削除はいくつかの方法がありますが、RailsではおおむねActiveRecordの4つのメソッドのうちどれかを使うことになります。  
delete, delete_all, destroy, destroy_allです。  
4つもあって混乱すると思いますが、そのエラーを出さないように削除するためには、

[code]

    @post = Post.find(params[:id]
    @post.destory
    
[/code]

という感じで消す必要があります。

上に揚げた4つのメソッド、大別して delete系とdestory系の二つに分かれているんですが、

  * delete系...実行するとActiveRecordが該当するDELETE文のSQLを生成し、そのまま実行する。ヴァリデーションやコールバックなど、ActiveRecordが更新系処理に付随して実行する処理は全てスキップされる。
  * destroy系...上と違い、ActiveRecordが更新系処理に付随して実行する処理を実行後に削除処理が実行される。

という違いがあります。

Postモデルに定義されている

[code]

     has_many :comments, dependent: :destroy
    
[/code]

これ。この依存関係の定義はコールバックに相当するので、delete系メソッドで削除した場合は実行されません。  
なのでメソッド実行時にすぐ下記のSQLが発行されます。

[code]

    DELETE FROM posts where id=xxxx
    
[/code]

CreateComments のマイグレーションファイルにFKの定義がある通り、

[code]

    t.references :post, foreign_key: true
    
[/code]

commentsテーブルのレコードは、常に親であるpostsテーブルのレコードのidを必ず持つように設定されています。  
コメントが残った状態でpostsレコードを消してしまうとコメントが孤児状態で浮いてしまうので、それを防止するためのFKのエラーが発生している訳ですね。  
このエラーを発生させないように、先にcommentsのレコードを消す必要がある訳ですが、そのためには `dependent: :destroy`
の定義だけでなく、destroyメソッドを使用する必要があります。


CC BY-SA 4.0
2021-01-21T15:14:08.457
73476
2021-01-21T15:14:08.457
43354
73428
answer