minennick
minennick

Reputation: 91

Comment function: undefined method `comment' for nil:NilClass

I want to create a function for comments for my rails application. Therefore only the current_user or an admin (I use active_admin) should be able to delete his comment. But I have trouble to figure that one out because my methods seem to point to nil. Can someone help me out, please?

comments_controller.rb

class CommentsController < ApplicationController
  before_action :correct_user,   only: :destroy

  def create 
    @post =Post.find(params[:post_id])
    @comment [email protected](params[:comment].permit(:name, :body))
    redirect_to post_path(@post)
  end

  def destroy 
    @post = Post.find(params[:post_id])
    @comment= @post.comments.find(params[:id])
    @comment.destroy
    redirect_to post_path(@post)
  end

  private
  def correct_user
    @user= User.find(current_user.id)
    redirect_to(root_url) unless current_user.id == @post.comment.user.id
  end

end

In my correct_user method the undefined comment shows up, so i already tried to add

@post = Post.find(params[:post_id])    
@comment= @post.comments.find(params[:id])

and tried different ways to make this run.

Comment.rb

class Comment < ApplicationRecord
  belongs_to :post
end

Post.rb

class Post < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy

  validates :title, presence: true, length: {minimum: 5}
  validates :body, presence: true
  validates :user, presence: true
  validates :user_id, presence: true
  has_attached_file :image  #, :styles => { :medium => "300x300>", :thumb => 
  "100x100>" }
  validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end

User.rb

class User < ApplicationRecord
 has_many :posts

 devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable  
end

PS: I want to do this rather with a before action, then with an if-statement around the delete link.

Upvotes: 0

Views: 650

Answers (2)

Kshitij
Kshitij

Reputation: 339

Try this,

 def destroy 
    @comment.destroy
    redirect_to post_path(@post)
  end

  private
  def correct_user
    @comment = Comment.find(params[:id])
    @post = @comment.try(:post)
    redirect_to(root_url) unless current_user.id == @post.try(:user_id)
  end

Here in params[:id] we are getting comment's id. Also this @comment.try(:post) and @post.try(:user_id) will work only if have associations as mentioned in your question.

Comment Model
belongs_to :post

Post Model
belongs_to :user 

Upvotes: 0

Stephan Rodemeier
Stephan Rodemeier

Reputation: 717

@post in #correct_user is nil since it's first set inside of #destroy. In addition, your Comment model does not currently have a relation with the User model, @post.comment.user.id won't work since #user will be undefined as well.

To correct this, add a relation between Comment and User only call @comment.destroy when the right user is calling the destroy action.

Upvotes: 1

Related Questions