Showing delete link for creator of comment - ruby-on-rails

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)

Related

Following users on Ruby on Rails

I decided to upgrade code of https://www.railstutorial.org/book chapter 14 Following users. My code does not work, when current_user goes on another page and open following. current_user sees himself and want to unfollow like original instagram. unfollow button does not work
show_follow.html.erb:
<div class="line-gray-modals"></div>
<% if #users.any? %>
<% #users.each do |user| %>
<ul class="follow-list">
<li><%= image_tag(user.avatar.url(:thumb), :class => "img-cirkle") %></li>
<li >
<div class="modal-follow-ns" > <div class="bold"> <%= link_to user.username, user %></div> <br>
<div class="modal-follow-ns2"><%= link_to truncate(user.status, :length => 50) %></div></div>
</li>
<li class="button-modal">
<% unless user == current_user %>
<div id="follow_form">
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
<% if user == current_user %>
<%= form_for(#user.relationships.find_by(followed_id: user),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% end %>
</li>
<%= will_paginate %>
<li> <div class="line-gray-modals"></div></li>
</ul>
<% end %>
relationships_controller.rb:
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
Terminal:
Completed 500 Internal Server Error in 10ms (ActiveRecord: 1.9ms)
NoMethodError (undefined method `destroy!' for nil:NilClass):
app/models/user.rb:28:in `unfollow!'
app/controllers/relationships_controller.rb:15:in `destroy'
Looking at the code below specially #user is probably nil. changing it to user does not make sense either. since you wanted to unfollow that user.
<%= form_for(#user.relationships.find_by(followed_id: user), html: { method: :delete }, remote: true) do |f| %>
Instead, use current_user
<%= form_for(current_user.relationships.find_by(followed_id: user), html: { method: :delete }, remote: true) do |f| %>

Ruby on rails getting article_id inside comments controller

So I am trying to get the article id to pass into the comments.article_id, I have looked all over - and can't find anything(I am fairly new so I doubt I know what I'm looking for) I have been trying for the last couple of hours to pass the articles id to the comments controller then set the comments.article_id to the article id. Here's my code at the moment:
ArticlesController:
class ArticlesController < ApplicationController
require 'comment'
def new
end
def create
#article = Article.new(article_params)
#article.user_id = current_user.id
if #article.save
flash[:success] = "Post created successfully!"
redirect_to article_path(#article)
else
flash[:danger] = "We could not create you're article!"
render 'new'
end
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
end
private
def article_params
params.require(:article).permit(:title, :description)
end
end
My comments controller:
class CommentsController < ApplicationController
def new
end
def create
#comment = Comment.new(comment_params)
#comment.article_id = Article.find(params[:id])
#comment.user_id = current_user.id
if #comment.save
flash[:success] = "Successfully created comment"
redirect_to article_path(#comment.article)
else
debugger
flash[:danger] = "Failed to create comment"
redirect_to article_path(2)
end
end
private
def comment_params
params.require(:comment).permit(:description)
end
end
and my show.html.erb for articles(because I am doing it all in there)
<h1 align="center">Title: <%= #article.title %></h1>
<div class="well col-xs-8 col-xs-offset-2">
<div class="row">
<div class="col-xs-4 col-xs-offset-4">
<div class="well well-sm">
<div class="user-img">
<p class="created">Created By:</p>
<%= gravatar_for #article.user, size: 150 %>
</div>
<div class="user-title">
<%= link_to #article.user.username, user_path(#article.user) %> <br />
</div>
</div>
</div>
</div>
<h4 class="center description"><strong>Description:</strong></h4>
<hr />
<%= simple_format(#article.description) %>
<div class="article-actions">
<% if logged_in? && current_user == #article.user %>
<%= link_to 'Edit', edit_article_path(#article), class: "btn btn-xs btn-primary" %>
<%= link_to 'Delete this article', article_path(#article), method: :delete,
data: { confirm: "Are you sure you want to delete this article?" },
class: "btn btn-xs btn-danger" %>
<%= link_to 'View all articles', articles_path, class: "btn btn-xs btn-success" %>
<% else %>
<%= link_to 'View all articles', articles_path, class: "btn btn-xs btn-success" %>
<% end %>
</div>
<% #article.comment.each do |f| %>
<div id="commentBorder">
<div class="panel panel-default">
<div class="panel-body">
<p><%= f.description %></p>
</div>
<div class="panel-footer">
<div align="center">
<small>Created by <%= f.user.username %>,<br />
<%= time_ago_in_words(f.created_at) %> ago</small></div>
</div>
</div>
</div>
<% end %>
<%= form_for(#comment, :html => {class: "form", role: "forms"}, :url => article_comments_path(#article)) do |comm| %>
<%= comm.label :description %>
<%= comm.text_field :description %>
<%= comm.submit "Post comment" %>
<% end %>
Solution!
So playing around some more literally five minutes after this, inside my Comments controller, I changed #comment.article_id = Article.find(params[:id])
Into
#comment.article_id = params[:article_id]
This fixed it, I have a theory on how so correct me if I am wrong.
From this picture you can see we already have article_id as a parameter(https://i.gyazo.com/fe49dcebbe75c006e95c7f44a9964865.png)
By using params[:article_id] we reached and got the article_id parameter and assigned it to our #comment.article_id value.
Just to be clear about rails associations, you could also have done :
#comment.article = Article.find(params[:article_id])
This has the advantage of ensuring the article exists before setting it's id value to the comment.article_id

Template is missing error when I destroy a comment using Ajax

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>

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? %>

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.

Resources