Template is missing error when I destroy a comment using Ajax - ruby-on-rails

All,
The destroy method in my comments controller is not finding the corresponding view when I delete a comment. I double checked my destroy.js.erb file and it looks correct. I double checked the comments controller as well and I couldn't find anything. In my _comment.html.erb file I have set the remote to true so it should find the corresponding app view to pick up. Can anyone offer any guidance?
Error message
Missing template comments/destroy, application/destroy with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby]}.
comments_controller.rb
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(params.require(:comment).permit(:body))
#comment.user = current_user
authorize #comment
if #comment.save #save the code down in the database
flash[:notice] = "Your comment was saved!"
else
flash[:error] = "Your comment failed to save."
end
redirect_to [#post.topic, #post]
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
authorize #comment
if #comment.destroy
flash[:notice] = "Comment was removed."
else
flash[:error] = "Comment couldn't be deleted. Try again."
end
#redirect_to [#post.topic, #post]
respond_to do |format| #tell controller to responde via Ajax
format.html #return response type in html
format.js #return response type in js
end
end
end
destroy.js.erb
<% if #comment.destroyed? %>
$('#comment-' +<%= #comment.id %>).hide();
$('.js-comments-count').html("<%= pluralize(#comment.user.comments.count, 'comment') %>");
<% else %>
$('#comment-' +<%= #comment.id %>).prepend("<div class='alert alert-danger'><%= flash[:error] %> </div");
<% end %>
_comment.html.erb
<div class="media">
<%= content_tag :div, class: 'media', id: "comment-#{comment.id}" do %>
<%= link_to '#', class: 'pull-left' do %>
<%= image_tag(comment.user.avatar.small.url, class: "media-object") if comment.user.avatar? %>
<% end %>
</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", [comment.post, comment], method: :delete, remote: true %>
<% end %>
</small>
<p><%= comment.body %></p>
</div>
</div>

The destroy.js.erb file was not able to find the comment.id within the div class. To fix the issue I removed the div class portion and the destory.js.erb was able to find the comment.id and my destroy.js.erb deleted the comment successfully with no error.
<%= content_tag :div, class: 'media', id: "comment-#{comment.id}" do %>
<%= link_to '#' do %>
<%= image_tag(comment.user.avatar.small.url) if comment.user.avatar? %>
<% end %>
<small>
<%= comment.user.name %> commented <%= time_ago_in_words(comment.created_at) %> ago
<% if policy(comment).destroy? %>
| <%= link_to "Delete", [comment.post, comment], method: :delete, remote: true %>
<% end %>
</small>
<p><%= comment.body %></p>

Related

nested edit path not working

Trying to figure out the edit path within _comment.html.erb file.
Keep getting this error:
ActiveRecord::RecordNotFound in CommentsController#edit
Couldn't find Article with 'id'=#<Comment::ActiveRecord_Associations_CollectionProxy:0x007fcac37359e8>
Don't know how to figure how to write the correct path.
Comments Controller
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
def show
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
def edit
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
_comment.html.erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<p>
<%= link_to 'Edit', edit_article_comment_path(#article.comments, comment) %>
</p>
<p>
<%= link_to 'Show', [comment.article, comment] %>
</p>
<p>
<%= link_to 'Destroy Comment', [comment.article, comment],
method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
routes
resources :articles do
resources :comments
end
How do I write the correct path?
Also, the earlier path I had was this:
<%= link_to 'Edit', edit_article_comment_path(#article, comment) %>
But it would turn up a blank edit form, ie, none of the text boxes had anything filled in ... hence why I tried the other path.
Any help would be appreciated.
Thank you.
Comment _form.html.erb
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Article show.html.erb
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Comments</h2>
<%= render #article.comments %>
<h2>Add a comment:</h2>
<%= render 'comments/form' %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
There's a problem in _comment.html.erb
<%= link_to 'Edit', edit_article_comment_path(#article.comments, comment) %>
It should be
<%= link_to 'Edit', edit_article_comment_path(#article, comment) %>
But it would turn up a blank edit form, ie, none of the text boxes had anything filled in
You should check if you are passing the proper values in form_for
<%= form_for [#article, #comment] do |f| %>
EDIT2
Well the problem is you are passing new instance of comment every time, Even with the edit action. That's why you are not getting any values in the form
<%= form_for([#article, #article.comments.build]) do |f| %>
Change it to
<%= form_for([#article, #comment]) do |f| %>
And make sure you are assigning #article and #comment in both new and edit action of CommentsController or from wherever you are rendering the comments/_form
class CommentsController < ApplicationController
def new
#article = Article.find(params[:article_id])
#comment = #article.comments.new
end
def edit
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
#...
end

Defining users within partials

I am new to ruby on rails, and know this is a beginner error. I'm trying to create an application that displays user comments within a post. I have a comment partial pointing to my post#show, and when requesting to display <%= image_tag(comment.user.avatar.small.url, class: "media-object") if comment.user.avatar? %> from _comment.html.erb, I get "undefined method 'user' for nil:NilClass. I've read other questions on stackoverflow and I know this is saying it can't find a user associated with the post within comments and that I need to define user in my controller. I'm assuming it's for the post controller, but I can't seem to wrap my head around the specific syntax to display comments by user in post.
#comments_controller
def create
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:post_id])
#comment = current_user.comments.new(comment_params)
#comment.post = #post
#comment.save
authorize #comment
redirect_to [#topic, #post]
end
#posts_controller
def show
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
end
#post model
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :topic
has_one :summary
has_many :comments
mount_uploader :image, ImageUploader
#comment model
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
#rendering comment partial in post#show
<h1><%= #post.markdown_title %></h1>
<div class="row">
<div class="col-md-8">
<small>
<%= image_tag(#post.image.thumb.url) if #post.image? %></br>
<%= 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><%= #post.markdown_body %></p>
</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 class="col-md-8">
<% if policy(Comment.new).create? %>
<%= render partial: 'comments/comment', locals: { comment: #comment } %>
<%= render partial: 'comments/form', locals: {topic: #topic, post: #post} %>
<% else %>
<h3>Sign up to Bloccit to post comments</h3>
<%= link_to "Sign up", new_user_registration_path, class: 'btn btn-primary' %></br></br>
<% end %>
#comment partial
<ul>
<% #post.comments.each do |c| %>
<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>
<li>
<p><%= c.body %></p>
</li>
</div>
<% end %>
Also, when I put #post.user = #user in posts_controller the error changes to "undefined method 'avatar' for nil:NilClass. Thanks for your help!
undefined method 'user' for nil:NilClass
The error is because of this line
<%= render partial: 'comments/comment', locals: { comment: #comment } %>
You don't have #comment initialized in show method of posts_controller and you are passing it as locals for comment, so comment.user returns error.
And also I've noticed that in _comment.html.erb you have this line <% #post.comments.each do |c| %>, so you can use c instead of comment.
<%= image_tag(c.user.avatar.small.url, class: "media-object") if c.user.avatar? %>
You are incorrectly referencing the block variable. Either change |c| to |comment| or change the comment references to c.
So like this:
<%= image_tag(c.user.avatar.small.url, class: "media-object") if c.user.avatar? %>

Couldn't find Post without an ID / ActiveRecord::RecordNotFound

I know this is a very basic solution however, I am just not seeing it right now. I am getting a 'Couldn't find Post without an ID' error within CommentsController#create.
I created a 'New Comment' button under the post which should then redirect to the comment form. From there once a user inputs their comments and clicks the 'Create Comment' button the comment should be displayed under the original post. Thank you in advance.
Comments Controller
Class CommentsController < ApplicationController
before_filter :authenticate_user!
def new
#comment = Comment.new
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:commenter, :body))
respond_to do |format|
if #comment.save
format.html { redirect_to #post, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
def show
#comment = Comment.new
end
end
Post/Show
<div class="row">
<div class="col-md-offset-4 col-med-8">
<div class="panel panel-default">
<div class="panel-heading center">
<% if #post.image.url %>
<%= image_tag #post.image.url(:medium) %>
<% elsif #post.video.url %>
<%= video_tag #post.video.url(:medium), controls: true, type: "video/mp4" %>
<% end %></br>
<p>
<strong>Likes:</strong>
<%= #post.get_likes.size%>
</p>
<%=link_to image_tag('like.jpg', :border => 0), likes_post_path(#post) %>
<%=link_to image_tag('unlike.jpg', :border => 0), dislikes_post_path(#post) %>
</div>
<div class="panel-body">
<p><%= #post.description %></p>
<% user = #post.user %>
<p><strong><%= link_to(user.name, user_path(user)) if #post.user %></strong></p>
<%= link_to 'New Comment', new_comment_path, class: "btn btn-danger btn-sm active" %></br>
<br><% if #post.user == current_user %>
<%= link_to edit_post_path(#post) do %>
<span class="glyphicon glyphicon-edit"></span>
Edit
<% end %>
<% end %>
<%= link_to 'Back', posts_path %>
</div>
</div>
</div>
Comments / _form
<%= form_for [#post, Comment.new] do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-danger btn-sm" %>
</div>
<% end %>
Routes
resources :comments
resources :posts do
resources :comments
end
Comments / Show
<p id="notice"><%= notice %></p>
<p>
<strong>Post:</strong>
<%= #comment.post_id %>
</p>
<p>
<strong>Body:</strong>
<%= #comment.body %>
</p>
<%= link_to 'Edit', edit_comment_path(#comment) %> |
<%= link_to 'Back', comments_path %>
Rake Routes
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
I recommend making the following changes:
Routes:
Remove the first resources :comments. Leave the following:
resources :posts do
resources :comments
end
Posts/Show view:
You should be using new_post_comment_path instead of new_comment_path. Run rake routes to see why.
CommentsController#new:
Define #post in your new action:
def new
#post = Post.find(params[:post_id])
#comment = Comment.new
end
Finally, in Comments/_form:
Change <%= form_for [#post, Comment.new] do |f| %> to <%= form_for [#post, #comment] do |f| %>. Although I believe <%= form_for #comment do |f| %> should work.
I recommend going through the Rails Guides for additional information and explanations.
I believe that in def new of the comments controller, you also need to set #post, not just #comment

form_for on commentables in rails

I'm having problems with the "First argument in form cannot contain nil or be empty" error that I haven't been able to find an answer for.
Basically, I have Posts, which show up on a User's show page, which should each have the option to comment on them. My routes are as follows:
resources :posts, only: [:create, :destroy] do
resources :comments, only: [:create, :destroy]
end
users/show.html.erb
<ol class="posts">
<%= render #posts %>
</ol>
posts/_post.html.erb
<li>
<span class="content"><%= post.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(post.created_at) %> ago.
</span>
<% if current_user?(post.user) %>
<%= link_to "delete", post, method: :delete,
data: { confirm: "You sure?" },
title: post.content %>
<% end %>
<span class="content">
<ul> Comments: <%= post.comments.count %></ul>
<% post.comments.each do |comment| %>
<ul> <%= comment.comment %> </ul>
<% end %>
</span>
<% if post != nil %>
<% form_for [post, #comment] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-lg btn-primary" %>
<% end %>
<% end %>
</li>
s comments_controller.rb
def create
#post = Post.find(params[:id])
#comment = #post.comments.build(comment_params)
#comment.user = current_user
if #comment.save
flash[:success] = "Posted!"
redirect_to #post
else
render 'static_pages/home'
end
end
def destroy
#comment.destroy
redirect_to root_url
end
Showing C:/app/views/posts/_post.html.erb where line #21 raised: (line 21 is the form_for line)
First argument in form cannot contain nil or be empty
app/views/posts/_post.html.erb:21:in _app_views_posts__post_html_erb___306000501_37434348'
app/views/users/show.html.erb:19:in_app_views_users_show_html_erb__480533737_37130988'
If each post had a show page, I know that I would put #posts on the show action and then make it an instance variable, but since the each post needs a separate comment dialogue box, I can't make it that general. It doesn't go through the posts controller though so I can't make it specific to each post. I'm using acts_as_commentable for the comments. Ideally, I would like to make them generic and put all the form_for comment stuff into a partial, but I'll figure that out later.

Showing delete link for creator of comment

I got my app working so that the user can only delete their own comments but now im trying to add a link to the site but i only want the creator of the comment to be able to see the link.
I tried doing
<% if current_user %>
but when i do that it shows up on all comments and not just the user. I can do
<% if current_user.admin %>
and that restricts only the admin to be able to see the delete links. I've also tried
<% if #comment.user_id == current_user.id %>
that doesent work either. How can i do it so that the comment creator can only see the comments?
heres my view
_comments.html.erb
<div class="container">
<% #comments.each do |comment| %>
<div class="comment">
<div class="gravatar_border">
<%= gravatar_for comment.user, size: '49' %>
</div>
<div class="user_info_comments">
<b><%= comment.user.name %></b>
<%= comment.created_at.strftime("%b. %d %Y") %>
</div>
<div class="user_comments">
<%= simple_format comment.content %>
<%= pluralize comment.reputation_value_for(:votes).to_i, "vote" %>
<%= link_to "", vote_comment_path(comment, type: 'up'), method: "post", class: ' icon-thumbs-up' %>
<%= link_to "", vote_comment_path(comment, type: 'down'), method: "post", class: ' icon-thumbs-down' %>
<% if #comment.user_id == current_user.id %>
<%= link_to 'delete', comment, method: :delete, confirm: 'you sure?' %>
<% end %>
</div>
</div>
<% end %>
<br />
</div>
heres my controller
comments_controller.rb
def destroy
#comment = Comment.find(params[:id])
if #comment.user_id == current_user.id
#comment.destroy
flash[:notice] = "comment deleted!"
else
flash[:error] = "not allowed"
end
redirect_to :back
end
heres a link to the site http://www.batman-fansite.com
Change #comment to comment in your view.
<% if comment.user_id == current_user.id %>
#comment is defined in your destroy action, but when you setup a block like this in your view
<% #comments.each do |comment| %>
#comment has no value, only comment does.
<% if comment.user_id == current_user.id %>
and should work)

Resources