ActiveRecord::RecordNotFound in CommentsController#destroy - ruby-on-rails

I am getting this error while i am going to delete a comment associated with a post.
// my CommentsController
def destroy
#post = Post.find(params[:post_id])
#comments = #post.comments.find(params[:comment])
#comments.destroy
redirect_to post_path(#post)
end
// my form::
<p>
<strong><%= comment.commenter %>: </strong>
<%= comment.body %>
<strong> at </strong><%= comment.created_at %>
<%= link_to 'Delete Comments', [comment.post,comment], method: :delete, data: {confirm: 'Are you Sure'} %>
</p>
I am getting the error in ::
#comments = #post.comments.find(params[:comment])
please tell me where i am wrong..

You probably should have:
#comment = #post.comments.find(params[:id])
#comment.destroy
Since by default, nested resource record id is referenced by params[:id] in destroy action.

Use this instead
#post = Post.where(:id => params[:post_id]).first
unless #post.blank?
#comment = #post.comments.where(:id => params[:id]).first
unless #comment.blank?
#comment.destroy
flash[:notice] = "Comment deleted"
redirect_to post_path(#post)
else
flash[:notice] = "Comment not found"
redirect_to post_path(#post)
end
end
The difference between find and where is that, where returns an empty array if no comment is found. But find raise an ActiveRecord::RecordNotFound error. Is it clear? If no comment of that id is present in the table then it will return an empty array, and in second line I have added a condition that if comment is not found don't perform destroy action. I've simply handled the error.
You have to include <%= flash[:notice] %> in view file to see the error/success message

Related

Delete comment link not working (acts_as_commentable)

In my Rails app, each post has a comment section where users can leave comments. I want each comment to have a delete link but I just can't get it to work. I am using the acts_as_commentable gem here.
posts/show.html.erb
<% #comments.each do |comment| %>
<p><strong><%= comment.user.username %></strong></p>
<p class="comment"><%= comment.comment %><p>
<%= link_to "Delete", [#post, comment], method: :delete %>
<% end %>
I need help with this line
<%= link_to("Delete", [#post, comment], method: :delete %>
comments_controller.rb
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
#comment.user_id = current_user.id
end
def destroy
#comment = Comment.find(params[:id])
redirect_to :back
end
Thanks for your help! :)
You are not destroying it at all in the destroy action, you need to add #comment.destroy to delete the comment from database
def destroy
#comment = Comment.find(params[:id]
#comment.destroy # add this line
redirect_to :back
end
Hope that helps!
change destroy action something like this:
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to :back
end
In this way you can make sure you are deleting comment related to specific post. It's rails proffered way you can look at it here .

ArgumentError: First argument in form cannot contain nil or be empty. Rails CRUD app,

I'm debugging an issue with what should be a fairly simple CRUD application for a course I'm taking. It's turning out to be more difficult than I imagined. I'm attempting to set it in the app so I can go into the question and either choose to edit or delete it. The delete works more or less just fine. But I get the following errors when I click the 'edit' button:
ActiveRecord::RecordNotFound in QuestionsController#edit - Couldn't find Question with 'id'=1 citing the edit method in my Questions controller.
Here's the error:
Extracted source (around line #13):
11 </div>
12 <div class="col-md-8">
13 <%= form_for #question do |f| %>
14 <div class="form-group">
15 <%= f.label :title %>
16 <%= f.text_field :title, class: 'form-control', placeholder: "Enter question title" %>
My controller:
class QuestionsController < ApplicationController
def index
#questions = Question.all
end
def new
#question = Question.new
end
def create
#question = Question.new(params.require(:question).permit(:title, :body, :resolved))
if #question.save
flash[:notice] = "Question was saved."
redirect_to #question
else
flash[:error] = "There was an error in saving your question. Please ask again."
render :new
end
end
def show
#question = Question.find(params[:id])
end
def new
#question = Question.new
end
def edit
#question = Question.find(params[:id])
end
def update
#question = Question.find(params[:id])
if #question.update_attributes(params.require(:post).permit(:title, :body))
flash[:notice] = "Post was updated."
redirect_to #question
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
def create
if #question.update_attributes(params.require(:question).permit(:title, :body, :resolved))
flash[:notice] = "Question was updated."
render :edit
redirect_to #question
else
flash[:error] = "There was an error saving your question. Please try again."
render :new
end
end
def delete
#question = Question.find(params[:id])
#question = Question.destroy
redirect_to #question
end
end
```
The view it's supposed to affect:
<h1><%= #question.title %></h1>
<p><%= #question.body %></p>
<%= link_to "Edit", edit_question_path(#question), class: 'btn btn-success' %>
<%= link_to "Delete", #question.delete, class: 'btn btn-danger' %>
And my routes file:
Rails.application.routes.draw do
resources :posts
resources :advertisements
resources :questions
resources :answers
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Any help you could give me would be much appreciated. I'm still kind of learning all of this.
You can view the repository for this project at https://github.com/InsomniaNoir/bloccit
You have <%= link_to "Delete", #question.delete, class: 'btn btn-danger' %> on your show view. So every time you get your show view it executes #question.delete and it deletes that #question. If you don't believe me visit a question then refresh the page you will see that your #question has been deleted. Replace that code with <%= link_to "Delete", #question, method: :delete, class: 'btn btn-danger' %>. I saw that in your git repository you commented out the edit action don't forget to uncomment it.

Nested Resource Sad Path Renders blank comment

I have a comment resource nested in a post resource.
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
#comment.ip = request.remote_ip
if #comment.save
redirect_to post_path(#post, notice: "Comment was successfully created")
else
flash[:alert] = "Comment could not be created"
render 'posts/show'
end
end
This all works well enough, but I have a nag item in that when the posts/show page with the comment form re-renders, it shows the comment that didn't pass validation inline. I'd like to know the correct way to do this, short of performing some logic in the view layer to not display a comment that isn't saved.
I ended up solving it in the view, because I couldn't find any other solution
<% #post.comments.each do |c| %>
<% unless c.new_record? %>
<strong><%= "#{c.name} wrote: " %></strong><br />
<blockquote><%= c.body %></blockquote>
<% end %>
<% end %>

Cannot redirect to Nil in CommentsController#destroy (Polymorphic association)

I am trying to write my delete method in my comment controller. My comment model has polymorphic associations with other models but in this case, we'll just focus on trips. In other words, #trip = #commentable.
The comment gets deleted just fine, but I keep getting the error ActionController::ActionControllerError in CommentsController#destroy: Cannot redirect to nil! when I redirect_to #commentable which would be the trip that the comment belonged to.
I also redirected to #commentable in my create action (comment controller) and that works just fine when the user creates a new comment.
Any tips?
view (trips/show.html.erb)
<% if !#commentable.comments.empty? %>
<% #commentable.comments.each do |comment| %>
<!-- Content -->
<%= link_to comment, :method => :delete do %> delete <% end %>
<% end %>
<% end %>
comment form that works for create action
<%= form_for [#commentable, Comment.new] do |f| %>
<%= f.text_area :content %>
<div id="comment_submit_button"><%= f.submit "Comment" %></div>
<% end %>
trips_controller.rb
def show
#trip = #commentable = Trip.find(params[:id])
#comments = Comment.all
end
comments_controller.rb
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to #commentable
end
end
def destroy
# #commentable = find_commentable this line was wrong
#comment = Comment.find(params[:id])
#commentable = #comment.commentable #this line fixed it
if #comment.destroy
redirect_to #commentable
end
end
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
Figured out the solution. Will post solution in code above.
def destroy
#comment = Comment.find(params[:id])
#commentable = #comment.commentable
if #comment.destroy
redirect_to #commentable
end
end

Rails makevoteable help creating user voting link and custom error message

I am having that problem with the gem makevoteable that when the page is loaded the post gets upvoted automatic. Instead of just having a link the user can click and upvote. When the page is reloaded I get the AlreadyVotedError in view. I would prefer a more user friendly error message as "You already voted this post"
My view:
<% #posts.each do |post| %>
<h1><%= post.titel %></h1>
<p><%= post.body_html %></p>
<p><%= link_to 'asdasdasd', current_user.up_vote(post) %>
<% end %>
UPDATE:
My route.rb: match 'stem_op/:id' => 'posts#vote_up', :as => 'stem_op'
My public controller:
def vote_up
#post = Post.find(params[:id])
current_user.up_vote(#post)
flash[:message] = 'Thanks for voting!'
redirect_to post_path(#post)
rescue MakeVoteable::Exceptions::AlreadyVotedError
flash[:error] = 'Already voted!'
redirect_to post_path(#post)
end
My view:
<% #posts.each do |post| %>
<h1><%= post.titel %></h1>
<p><%= post.body_html %></p>
<p><%= link_to 'Stem op', stem_op_path(post.id) %>
</tr>
<% end %>
When I try to vote_up a post I get this error:
Template missing - Do I really need a blank view file?
UPDATE:
def vote_up
#post = Post.find(params[:id])
current_user.up_vote(#post)
flash[:message] = 'Thanks for voting!'
redirect_to post_path(#post)
rescue MakeVoteable::Exceptions::AlreadyVotedError
flash[:error] = 'Already voted!'
redirect_to post_path(#post)
end
Error:
SyntaxError in PostsController#vote_up
C:/Rails/den/app/controllers/posts_controller.rb:103: syntax error, unexpected keyword_end, expecting $end
Yes, current_user.up_vote(post) adds a vote for that user. You need to create a controller action that executes current_user.up_vote(post) and handles the flash message. Then you can link to that action in your view.
Edit to answer comment:
guides.rubyonrails.org/action_controller_overview
In your posts controller I imagine you would want something like:
def upvote
#post = Post.find params[:id]
current_user.upvote(#post)
flash[:message] = 'Thanks for voting!'
redirect_to post_path(#post)
rescue MakeVoteable::Exceptions::AlreadyVotedError
flash[:error] = 'Already voted!'
redirect_to post_path(#post)
end
and in your routes something like:
map.resource :post do
member do
post :upvote
end
end
Your link would become link_to 'Upvote!', upvote_post_url(post), :method => :post

Resources