Reputation: 1374
I am a new student to Ruby on Rails and am currently working on the Deletion HTTP request for my project, a Reddit clone. So far I have implemented Destroy functionality on Topics and Posts successfully. Now that I am working on the deletion of Comments I have hit an error that I am not sure how to deal with.
Here was the instruction.
Finally, we also have to modify the comment-listing view -- the app/views/comments/_comment.html.erb partial called in posts#show. Update the partial to look this:
<div class="media">
<div class="media-left">
<%= image_tag(comment.user.avatar.small.url, class: "media-object") if comment.user.avatar? %>
</div>
<div class="media-body">
<small>
<%= comment.user.name %> commented <%= time_ago_in_words(comment.created_at) %> ago
<% if policy(comment).destroy? %>
| <%= link_to "Delete", [@topic, @post, comment], method: :delete %>
<% end %>
</small>
<p><%= comment.body %></p>
</div>
</div>
My _comment.html.erb before the change:
<% @comments.each do |comment| %>
<p><%= comment.body %></p>
<p><i><%= comment.user.name %></i></p>
<% end %>
After modifying the code as instructed I receive this error:
NoMethodError at /topics/4/posts/11 undefined method `avatar?' for nil:NilClass
With this line highlighted:
<%= image_tag(comment.user.avatar.small.url, class: "media-object") if comment.user.avatar? %>
Here is my views/post/show.html.erb:
<h1><%= markdown_to_html @post.title %></h1>
<div class="row">
<div class="col-md-8">
<small>
<%= image_tag(@post.user.avatar.tiny.url) if @post.user.avatar? %>
submitted <%= time_ago_in_words(@post.created_at) %> ago by
<%= @post.user.name %>
</small>
<p><%= markdown_to_html @post.body %></p>
<p><%= image_tag(@post.image.post.url) if @post.image? %>
<h1>Comments</h1>
<!-- render the comments loop -->
<%= render partial: 'comments/comment', locals: { topic: @topic, post: @post, comment: @comment } %>
<!-- render the comments form if user is signed in -->
<% if policy(@comment).create? %>
<%= render partial: 'comments/form', locals: { topic: @topic, post: @post, comment: @comment } %>
<% end %>
</div>
<div class="col-md-4">
<% if policy(@post).edit? %>
<%= link_to "Edit", edit_topic_post_path(@topic, @post), class: 'btn btn-success' %>
<% end %>
<% if policy(@post).destroy? %>
<%= link_to "Delete Post", [@topic, @post], method: :delete, class: 'btn btn-danger', data: { confirm: 'Are you sure you want to delete this post?' } %>
<% end %>
</div>
</div>
comments controller
class CommentsController < ApplicationController
def create
# find topic by id
@topic = Topic.find(params[:topic_id])
# find post id through topic
@post = @topic.posts.find(params[:post_id])
# comments on post
@comments = @post.comments
@comment = current_user.comments.build(params.require(:comment).permit(:body, :post_id, :avatar))
@comment.post = @post
authorize @comment
if @comment.save
flash[:notice] = "Comment was created."
redirect_to [@topic, @post]
else
flash[:error] = "Error saving the comment. Please try again."
# must render the the page calling the form!!
render 'posts/show'
end
end
def new
end
def destroy
@topic = Topic.find(params[:topic_id])
@post = Post.posts.find(params[:post_id])
@comment = @post.comments.find(params[:id])
authorize @comment
if @comment.destroy
flash[:notice] = "Comment was removed."
redirect_to [@topic, @post]
else
flash[:error] = "Comment couldn't be deleted. Try again."
redirect_to [@topic, @post]
end
end
end
user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :posts
has_many :comments
# CarrierWave method for attribute functionality
mount_uploader :avatar, AvatarUploader
# These methods check the role of a user in the database
def admin?
role == 'admin'
end
def moderator?
role == 'moderator'
end
end
I have attempted to change my comment.user.avatar.small.url to @comment.user.avatar.small.url based off how the rest of my images were handled in the project. The error still persists.
Best regards.
Upvotes: 1
Views: 583
Reputation: 226
This is error means that comment.user
is nil
. If you want to fix it you should investigate why this happens.
If this is the correct case (for example this is an anonymous user) then you can handle it use something like:
... if comment.user.try(:avatar?)
Upvotes: 3