th_9plus
@th_9plus (たかちゃん)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Ruby on rails 投稿削除エラー

コメント機能実装中です。
コメントの削除はできるのですが
コメントが付いていない投稿を削除しようとした時にエラーが出るようになってしまいました。
色々試して見ましたが解決できませんでした。教えて頂きたいです。
よろしくお願い致します。

NameError in PostsController#destroy
undefined local variable or method `c' for #<PostsController:0x00007fc9403b6670>
Extracted source (around line #54):
52
53
54
55
56
57


def destroy
unless c.user_id == cuirrent_user.id
flash[:notice] = "コメントを削除しました"
end
@post = Post.find_by(id: params[:id])
posts/show.html
<div class="comment-wrapper">
      <p>コメント一覧</p>
      <% @comments.each do |c| %>
        <div class="user-comment">
          <% unless c.user.blank? %>
           <img src="<%= "/user_images/#{c.user.image_name}" %>">
          <% end %>
          <%= c.user.name unless c.user.blank? %>
          <br />
          <%= c.content %>
         <% if c.user_id == current_user.id %>
           <%= link_to "削除", comment_path(c), method: :delete, class: "comment-menus" %>
          <% end %>
        </div>
        <br />
class PostsController < ApplicationController
    before_action :authenticate_user
    before_action :ensure_correct_user, {only: [:edit, :update, :destroy]}

  def index
    @posts = Post.all.order(created_at: :desc)
  end

  def show
  
    @post = Post.find_by(id: params[:id])
    @user = @post.user
    @post = Post.find(params[:id])
    @comments = @post.comments
    @comment = Comment.new
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(
      content: params[:content],
      user_id: @current_user.id,
     )
     if params[:post].present?
      @post.video = params[:post][:video]
      print params
     end
    if @post.save
     flash[:notice] = "投稿を作成しました"
     redirect_to("/posts/index")
    else
     render("posts/new")
    end
  end

 def edit
   @post = Post.find_by(id: params[:id])
 end

 def update
    @post = Post.find_by(id: params[:id])
    @post.content = params[:content]
   if @post.save
    flash[:notice] = "投稿を編集しました"
    redirect_to("/posts/index")
   else
    render("posts/edit")
   end
 end

 def destroy
  unless c.user_id == cuirrent_user.id
   flash[:notice] = "コメントを削除しました"
  end
   @post = Post.find_by(id: params[:id])
   @post.destroy
   flash[:notice] = "投稿を削除しました"
   redirect_to("/posts/index")
 end

 def ensure_correct_user
     @post = Post.find_by(id: params[:id])
     if @post.user_id != @current_user.id
       flash[:notice] = "権限がありません"
       redirect_to("/posts/index")
     end
 end
end
post.rb
class Post < ApplicationRecord

  {length: {maximum: 140}}
  validates :user_id, {presence: true}
  has_many :comments, dependent: :destroy
  mount_uploader :video, VideoUploader
  mount_uploader :picture, PictureUploader
  def user
    return User.find_by(id: self.user_id)
  end

end

試した事

unless @commnts.user_id == cuirrent_user.id に変更ししましたがnilのエラーが出ます。

NoMethodError in PostsController#destroy
undefined method `user_id' for nil:NilClass
Extracted source (around line #54):
52
53
54
55
56
57


def destroy
unless @commnts.user_id == cuirrent_user.id
flash[:notice] = "コメントを削除しました"
end
@post = Post.find_by(id: params[:id])

デバックしたところnilの確認はできました。

def destroy
p "=================="
p @comments
p "==================="
unless @commnts.user_id == cuirrent_user.id
flash[:notice] = "コメントを削除しました"
end
"=================="
nil
"==================="
0

2Answer

controller側でURLのパラメーターを元にDBからコメントのデータを持ってくる処理を書く必要があります。
サーバーはステートレスなので、リクエスト先ではリクエスト元のインスタンスを参照することはできません。
destroyの中でComment.findなどを用いてデータをロードしましょう。
https://www.websec-room.com/2013/02/23/178

1Like

Comments

  1. @th_9plus

    Questioner

    ```
    def destroy
    if params[:comments].present?
    @commnts.user_id == cuirrent_user.id
    flash[:notice] = "コメントを削除しました"
    end
    @post = Post.find_by(id: params[:id])
    @post.destroy
    flash[:notice] = "投稿を削除しました"
    redirect_to("/posts/index")
    end
    ```
    こちらに変更したら削除できるようになりました!
    ありがとうございます!

@th_9plus

https://qiita.com/th_9plus/questions/2823418a73b964314e6e#answer-d1f5cb45b7b4f294774f の回答コメントのコードがちょっと気になったのでコメントします。

以下のように find で検索するようにした方が良いと思います。

def destroy
  ...

  @post = Post.find(params[:id])
  @post.destroy

   ...
end

もし存在しない id が指定された場合、 find_byは nil を返すため@post.destroy がnilエラーになってしまいます。

find を使っておけば、ActiveRecord::RecordNotFound 例外を投げてくれます。
別途エラーハンドリングは必要ですが、ここの処理を単純化できます。

参考:

0Like

Comments

  1. @th_9plus

    Questioner

    わかりました!
    丁寧にありがとうございます!

Your answer might help someone💌