How can I delete comments in a rails blog app? - ruby-on-rails

I'm new to rails, I have followed the Blogger tutorial from Jumpstart Labs to make a blogging app, and I am trying to implement a feature that will allow users who are logged in to delete comments on articles.
but I keep getting confused by this error message "ActiveRecord::RecordNotFound in CommentsController#destroy
Couldn't find Article with 'id'="
here's what I've managed so far,
this is my app/controllers/comments_controller.rb
class CommentsController < ApplicationController
before_filter :require_login, except: [:create]
def create
#comment = Comment.new(comment_params)
#comment.article_id = params[:article_id]
#comment.save
redirect_to article_path(#comment.article)
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(:author_name, :body)
end
end
and my /views/articles/show.html.erb
<h1><%= #article.title %></h1>
<p>
<b>Posted on <%= #article.created_at.strftime("%B %d %Y") %></b>
</p>
<p>
<% if #article.image.exists? %>
<%= image_tag #article.image.url%>
<% end %>
</p>
<p><%= #article.body %></p>
<%= render partial: 'comments/form' %>
<% if logged_in? %>
<%= link_to "Edit", edit_article_path(#article) %>
<%= link_to "delete", article_path(#article), method: :delete%>
<% end %>
<%= link_to "<< Back to Articles List", articles_path %>
<h3>Comments (<%=#article.comments.size %>) </h3>
<%= render partial: 'articles/comment',
collection: #article.comments %>
<p>
Tags:
<% #article.tags.each do |tag| %>
<%= link_to tag.name, tag_path(tag) %>
<% end %>
</p>
app/views/articles/comment.html.erb
<div>
<p><b>Comment by:</b> <%= comment.author_name %></p>
<p class="comment"><%= comment.body %></p>
<p>Posted <%= distance_of_time_in_words(comment.article.created_at, comment.created_at) %> later</p>
<%= link_to 'Delete Comment', article_comment(article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
</div>
routes.rb
Blogger::Application.routes.draw do
get 'about', to: 'info#about'
get 'portfolio', to: 'info#portfolio'
get 'contact', to: 'info#contact'
root to: 'articles#index'
resources :articles do
resources :comments
end
resources :tags
resources :authors
resources :author_sessions, only: [ :new, :create, :destroy ]
get 'login' => 'author_sessions#new'
get 'logout' => 'author_sessions#destroy'
end
and my articles_controller
class ArticlesController < ApplicationController
include ArticlesHelper
before_filter :require_login, only: [:new, :create, :edit, :update, :destroy]
def index
#articles = Article.all
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
#article.save
flash.notice = "Article '#{#article.title}' Created!"
redirect_to article_path(#article)
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#article.update(article_params)
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:id])
#article.destroy
flash.notice = "Article '#{#article.title}' Deleted!"
redirect_to articles_path
end
end
Any input or advice greatly appreciated, I've been looking around google and stack overflow for a while but I haven't found a solution yet

The error NameError in Articles#show undefined local variable or method article can be fixed by changing this line in app/views/articles/_comment.html.erb (I believe it has _)
from
<%= link_to 'Delete Comment', article_comment(article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
to
<%= link_to 'Delete Comment', article_comment_path(comment.article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
And in views/articles/show.html.erb, try to change collection: #article.comments to collection: #article.comments.all.

To get past that particular error your having you need to permit the :id and :article_id params
Add them like this
params.require(:comment).permit(:author_name, :body, :id, :article_id)

Related

Rails - ActiveRecord::RecordNotFound (Couldn't find Comment with 'id'=27):

I'm building an Event app using Rails and have comments as a nested resource. I'm trying to implement an Edit function using Ajax/in-line editing but my Edit link isn't working.
I'm not getting an error up on screen but I am getting above error from my development log. The comment 'id' = 27 relates to the event_id not the comment id. How do I rectify this?
Here's the relevant code -
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_event, only: [:show, :create, :edit, :update, :destroy]
before_action :set_comment, only: [:show, :create, :edit, :update, :destroy]
def create
#comment = #event.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to #event
else
render 'new'
end
end
# GET /comments/1/edit
def edit
respond_to do |f|
f.js
f.html
end
end
def show
end
def update
if #comment.update(comment_params)
redirect_to #event, notice: "Comment was successfully updated!"
else
render 'edit'
end
end
def destroy
#comment.destroy
redirect_to event_path(#event)
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def set_event
#event = Event.find(params[:event_id])
end
def comment_params
params.require(:comment).permit(:name, :body)
end
end
_comment.html.erb
<div class="comment clearfix">
<div class="comment_content">
<div id="<%=dom_id(comment)%>" class="comment">
<p class="comment_name"><strong><%= comment.name %></strong></p>
<p class="comment_body"><%= comment.body %></p>
</div>
<% if user_signed_in? %>
<p><%= link_to 'Edit', edit_event_comment_path(#event, #comment.event), id: "comment", remote: true %></p>
<p><%= link_to 'Delete', [#comment.event, comment],
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' } %></p>
<% end %>
</div>
</div>
edit.js.erb
$('#comment').append('<%= j render 'form' %>');
_form.html.erb
<%= simple_form_for([#event, #comment], remote: true) do |f| %>
<%= f.label :comment %><br>
<%= f.text_area :body %><br>
<br>
<%= f.button :submit, label: 'Add Comment', class: "btn btn-primary" %>
<% end %>
I've checked the routes and they're all as they should be.I can't check whether the in-line editing will work unless I fix this first.
As far as I can see you have two before actions, set_event and then set_comment.
If you've set both of these to look for params[:id], then it means they will obviously both be using the same value for a search. You will need to change one of them, let us say set_event, to something like:
def set_event
#event = Event.find(params[:event_id])
end
You will also have to change your routes to account for the new id. If you are using your standard resource routes:
resources :events, param: event_id do
resources :comments
end
This will give you routes such as:
localhost:3000/events/:event_id/comments/:id
Which you can then use to find your events and comments.

NoMethodError in PostsController#upvote undefined method `upvote_by' for nil:NilClass

screenshot
Currently I'm using acts_as_votable gem along with bootstrp-sass gem,I want to upvote the post when glyphicon icon is clicked, instead it throws me above errors.
This is my posts_controller.rb file
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :date, :time, :location))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to root_path
end
def upvote
#post.upvote_by current_user
redirect_to :back
end
private
def post_params
params.require(:post).permit(:title, :date, :time, :location)
end
end
This is my show.html.erb file
<div id="post_content">
<h1 class="title">
<%= #post.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
| <%= link_to 'Edit', edit_post_path(#post) %>
| <%= link_to 'Delete', post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</p>
<p class="date">
<%= #post.date %>
</p>
<p class="time">
<%= #post.time %>
</p>
<p class="location">
<%= #post.location %>
</p>
<div id="comments">
<div class="btn-group pull-left">
<%= link_to like_post_path(#post), method: :put, class: "btn btn-default" do %>
<span class="glyphicon glyphicon-heart"></span>
<%= #post.get_upvotes.size %>
<% end %>
</div>
<h2><%= #post.comments.count %> Comments</h2>
<%= render #post.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
This is my routes.rb file
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
resources :posts do
resources :comments
collection do
get 'search'
end
member do
put "like", to: "posts#upvote"
end
end
root "posts#index"
get '/about', to: 'pages#about'
end
And this is my post model
class Post < ActiveRecord::Base
acts_as_votable
searchkick
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :date, :time, :location, presence: true
belongs_to :user
end
NoMethodError in PostsController#upvote undefined method `upvote_by'
for nil:NilClass
The error is because you didn't initialized #post in upvote method so #post is nil
def upvote
#post = Post.find(params[:id])
#post.upvote_by current_user
redirect_to :back
end

Syntax Error with rails unexpected ')'

Hi there I want to add a destroy action in post#show view I think I have creates the environment but when I place this code with a condition I have a message error.
<% if #user.comment == current_user %>
<% link_to #post_comment_path(post_id: #post.id, id: comment.id), method: :delete, data: { confirm: "Are you sure?" } do %>
<i class="fa fa-trash"></i>
<% end %>
<% end %>
I created a partial in post show#view which names _comments.html.erb
here it is
<p class="text-center">Poster un commentaire</p>
<%= simple_form_for [post, post.comments.new] do |f| %>
<%= f.error_notification %>
<%= f.input :content, label: "Commentaire"%>
<%= f.submit "Envoyer", class: "btn btn-primary" %>
<% end %>
and it render like that <%= render 'comments' %>
and above the partial (in post show#view) I do an iteration like that
<ul class="list-unstyled">
<% #post.comments.each do |comment| %>
<li>
<p><% comment.content %></p>
<% end %>
</li>
</ul>
But nothing appears when I create a new message, I don't userstand why.
I give your more code details
post.rb
has_many :comments, dependent: :destroy
comment.rb
belongs_to :user
belongs_to :post
The route is:
resources :posts do
resources :categories
resources :comments
end
Comments controller is
class CommentsController < ApplicationController
before_action :set_post
def create
#comment = #post.comments.build(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:success] = "You commented the hell out of that post!"
redirect_to :back
else
flash[:alert] = "There is a problem with your comment"
render root_path
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
flash[:success] = "Comment deleted :("
redirect_to root_path
end
private
def set_post
#post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:content, :post_id, :user_id)
end
end
Thank you so much for your help.
Your link_to erb code needs an equals sign for it to actually display
<%= link_to post_comment_path(post_id: #post.id, id: comment.id), method: :delete, data: { confirm: "Are you sure?" } do

Grab only text from blog post that includes image, tables, etc

I'm using Rails 4.0.0 and CKEDITOR to build out a small blog for a client, and I'm having an issue with the page that displays the ten most recent posts and a small excerpt.
If an image was inserted into the post, or a table, or any other html element, that is coming over as well.
Can I just grab the text, without image, tables, etc?
Here is my controller code:
class PostsController < ApplicationController
before_filter :authorize, only: [:new, :create, :edit, :update]
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post].permit(:title, :text, :photo))
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :text, :photo))
redirect_to #post
else
render 'edit'
end
end
def destroy
Post.find(params[:id]).destroy
redirect_to posts_path
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text, :photo)
end
end
And my view code:
<% #body_class = "blog" %>
<div class="wrap">
<h1>Listing posts</h1>
<p><%= link_to 'New post', new_post_path, 'data-no-turbolink' => 'false' %></p>
<% #posts.each do |post| %>
<div class="post" id="<%= post.id %>">
<div class="postTitle">
<%= post.title %>
</div>
<div class="postContent">
<%= post.text.html_safe %><br/><br/>
<%= link_to 'Show', post_path(post) %>
<% if current_user %>|
<%= link_to 'Edit', edit_post_path(post), 'data-no-turbolink' => 'false' %> |
<%= link_to 'Destroy', post_path(post), :confirm => 'Are you sure you want to delete this post?', :method => :delete %>
<% end %>
</div>
</div>
<% end %>
</div>
Thanks all!
My last resort will be to just create a new column in the database for an "Excerpt that they can write themselves. That may be a better idea anyways.
You need strip_tags plus truncate
truncate(strip_tags(post.text), length: 100, separator: ' ')
And you should save the result in before_save callback into special field you talked about for optimization.

New post - First argument in form cannot contain nil or be empty

This is error I'm getting when I click on "New Post:
First argument in form cannot contain nil or be empty
My PostController:
class PostsController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def edit
end
def update
#post.update(post_params)
redirect_to posts_path
end
def new
if user_signed_in?
#post = Post.new
else
flash[:alert] = ":("
end
end
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
#post.save
redirect_to posts_path
end
def destroy
if user_signed_in?
#post.destroy!
else
flash[:alert] = ":("
end
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:body)
end
def set_user
#post = Post.find(params[:id])
end
end
and posts#index:
<% #posts.each do |post| %>
<%= post.body %>
<%= link_to 'Show', post %>
<%= link_to 'Edit', edit_post_path(post) %>
<%= link_to 'Delete', post, method: :delete %>
<br>
_form.html.erb
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
you should check your "new.html.erb" or "_form.html.erb" file. to see if the "form_for" method is correctly called.
If you are using devise, You can get this by adding a before action:
before_action :authenticate_user!, only: [:new]
and you new action as:
def new
#post = Post.new
end

Resources