controllerでのdestroy対象に漏れがあった
投稿を削除した後にログインしている人のユーザーホームに移動しようとしたらエラーになった
NoMethodError in Users#show
undefined method `story' for 2:Integer
ActionView::Template::Error (undefined method `story' for nil:NilClass):
コンソールで見るとlikeは取れているが
like.impressionはnil
ライクはあるのにそれにひもづいた感想がない
なんで感想がないのか思い至らなかったが感想を消した時に原因がありそうに思った(レッスン中)
HTML
<% likes.each do |like| %>
<div class="user_story">
<%= like.user.nicename %>
<%= like.impression.impressions %> # 今回のエラー箇所
</div>
<% end %>
ユーザー詳細ページにrenderされている
投稿を削除したときのdestoryの指定が甘かったのでいくつか生き残った欠片がエラーの原因
ユーザー詳細画面には自分の投稿を見ることのできる_user.html.erb
と、
自分がお気に入りした投稿を見ることのできる_like.html.erb
をつくってあるが
お気に入りの方_like.html.erb
でエラーが出た
コントローラー修正前
def destroy
@book = Book.find(params[:id])
@impression = Impression.find(params[:id])
@impression.destroy
@book.destroy
redirect_to "/index"
end
上のコードだと
・感想に紐づいたLikeが削除されない
・コメントも削除されない
・二つともparams[:id]を使って探しているがもしidが違った場合エラーの原因になる
なので
・取得するデータの起点を一つにして連鎖的に投稿に紐づくデータを削除させる
・Likeを取得してdestroyさせたい
コントローラー修正後
def destroy
# params[:id] と impression.id は同じになっている
@book = Book.find(params[:id])
@impressions = @book.impressions
@impressions.each do |impression|
@likes = impression.likes
@likes.each do |like|
like.destroy
end
impression.destroy
end
@book.destroy
redirect_to "/index"
end
本のデータを探して、見つかった感想たちを回してライクを取得してdestroyする
コメントも取得して消しておく。作業はlikeと同じ。エラーでなかったから忘れていた作業です
:dependent => :destroyは失敗
:dependent => :destroyだけだと同じエラーになったので、更に子モデルに:dependent => :nullifyを指定したけれどlike,commentまで消えてくれなかった
has_many :impressions, :dependent => :destroy
has_many :comments, :dependent => :nullify
has_many :likes, :dependent => :nullify
@book = Book.find(params[:id])
@book.destroy
redirect_to "/index"
問題はコントローラーにありそうだけれどもなんでしょうね。
追記
頂いたコメント通りに試しに子モデルに当てていた
:dependent => :nullify
を
:dependent => :destroy
に変えてみたところ、要素の削除に成功しました。
ありがとうございます
has_many :comments, :dependent => :destroy
has_many :likes, :dependent => :destroy
外部キーとは他のテーブルのidを指し示すものだとのこと
読んでくれてありがとう