Buggy Comments Code with Rails App - ruby-on-rails

So for some reason my code seems to have a mind of its own and will work at some points and then other times will throw an error saying undefined name method when trying to run this code in the view
<%= div_for comment do %>
<p>
<big><%= h(comment.body) %> - <%= link_to comment.user.name, comment.user %> </big><br />
Posted <%= time_ago_in_words(comment.created_at) %> ago
</p>
<% end %>
The code for my comments controller looks like this
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
#comment.user_id = current_user.id
#comment.save
respond_to do |format|
format.html { redirect_to #post}
format.js
format.json { render :json => #comments }
end
end
Like I said sometimes this code works fine and sometimes it doesn't. I'm not sure whats causing the problem, whats even more weird is that in my localhost its working fine but when I push the code to my domain it doesn't work. Before you say it may be a domain rails version mismatch you should know this problem has occurred on my localhost as well before and then resolved itself magically without me changing any code. If anyone could help me it would be greatly appreciated.
Edit: Here is the error log you requested
Completed 500 Internal Server Error in 286ms
ActionView::Template::Error (undefined method `name' for nil:NilClass):
1: <%= div_for comment do %>
2: <p>
3: <big><%= h(comment.body) %> - <%= link_to comment.user.name, comment.user.name %></big><br />
4: Posted <%= time_ago_in_words(comment.created_at) %> ago
5: </p>
6: <% end %>
app/views/comments/_comment.html.erb:3:in `block in _app_views_comments__comment_html_erb___3516162043769402279_2170426440__2165839557434581766'
app/views/comments/_comment.html.erb:1:in `_app_views_comments__comment_html_erb___3516162043769402279_2170426440__2165839557434581766 '
app/views/posts/show.html.erb:14:in `_app_views_posts_show_html_erb__667623582898069867_2171134300_136023206927572946'
app/controllers/posts_controller.rb:23:in `show'

You may checkout the value of comment.user when the error occurs. It seems that comment.user is not an object User as you expect. Checkout your database, maybe some comments are not associated with users or associated with non-existant users.
You can try to debug like this when you'll have the error again:
<% comments.each do |comment| %>
<%= debug comment %> // Or comment.user
<% end %>

Related

Rails doesn't send object as a param error

I've got a controller that handles articles, and recently implemented the edit and create action that way:
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render :edit, status: :unprocessable_entity
end
end
The error occours when I try to edit an article showing the message: screenshot
I'm using a form partial to load the layout this way:
<%= render "form", article: #article %>
After trying to save an new article the edit action works properly and the body error message doesn't shows if trying to save without the requirements. What should I do so solve this problem?
Thanks in advance.
There is a better way altogether to handle rendering errors - just access the object wrapped by the form builder:
<%= form_with(model: article) do |form| %>
<% if form.object.errors.any? %>
<ul>
<% form.object.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
<% end %>
# ...
<% end %>
This lets you DRY out the rendering of errors messages without having to know the name of variable which corresponds to the model instance wrapped by the form.
However you also have a classic nil error - #article is most likely nil. And this isn't an issue we can actually help you with since it cannot be reproduced if we take the code in the question at face value. Like often with stackoverflow the actual problem it lurking somewhere outside of picture.
The debug this code you need to ensure that the code you think is running is actually running and set a series of breakpoints to verify that it is indeed being set and is being passed correctly all the way to the view.
I see that you change article to #article in edit.html.erb. Because article does not exist. article exists when you render "form", article: #article use in _form.html.erb
<% #article.erors.full_messages_for(:title).each do |message|
<div><%= message %></div>
<% end %>
But i think you don't show errors in edit.html.erb
In edit.html.erb file
<%= render "form", article: #article %>
In _form.html.erb
<%= form_with(model: article) do |form| %>
<% if article.errors.any? %>
<ul>
<% article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
<% end %>
<div>
<%= form.label :title, class: "form-control" %>
<%= form.text_field :title %>
</div>
<div>
<%= form.submit, class: "btn btn-primary" %>
</div>
<% end %>
P/S: That's my opinion, if anyone has any ideas, please leave a comment. I thank you very much

Ruby on Rails Tutorial (Michael Hartl) Chapter 2 Exercise 2.3.3.1 "Edit the user show page to display the content of the user’s first micropost."

Full descriptions of task sounds:
Edit the user show page to display the content of the user’s first micropost. (Use your technical sophistication (Box 1.1) to guess the syntax based on the other content in the file.) Confirm by visiting /users/1 that it worked.
My first idea was to update app/views/users/show.html.erb into
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
</p>
<p>
<strong>Content:</strong>
<%= #micropost.content %>
</p>
<%= link_to 'Edit', edit_user_path(#user) %> |
<%= link_to 'Back', users_path %>
But seems I haven't got idea behind task? Any suggestions from what I should start from?
Biggest thanks for your responses)
You should be getting an Undefined method 'content' for nil:NilClass error. The problem is that #micropost is not defined in the controller method (action) and so is nil.
And you can't call the content method on a nil object since it doesn't respond to it. In other words, there is no instance method named content defined on NilClass.
To fix the error, define an instance variable #micropost in the show action of UsersController.
# users_controller.rb
def show
#user = User.find(params[:id])
#micropost = #user.microposts.first
end
#user.microposts.first returns user's first post.
If the user has no posts associated with them, #user.microposts.first will return nil. So, you have to check if #micropost is nil before displaying it in the view.
# users/show.html.erb
<% if #micropost %>
<p>
<strong>Content:</strong>
<%= #micropost.content %>
</p>
<% end %>
I think you might be able to just do this in the users/show.html.erb:
#user.microposts.first.content
While not elegant, it's the simplest and satisfies the "edit the user show page" requirement of the exercise.
I also added #user.id because without it you don't know which user to add the microposts to for testing. Then you need to test to see if there is a microposts in order not break the code trying to display nil.
<p>
<strong>ID:</strong>
<%= #user.id %>
</p>
<% if #user.microposts.first %>
<p>
<strong>First Post:</strong>
<%= #user.microposts.first.content %>
</p>
<% end %>

Internal Server Error ajax Rails

In my show view I have this div:
<% if #question.answers.any? %>
<div class="parent">
<%= render :partial => #question.answers %>
</div>
<% else %>
<p class="hideAns">No answers yet. Be the first first to answer!</p>
<% end %>
As shown from the code above, I am displaying a paragraph if the question has no answers. The problem that I am facing is checking if the question has answers again with ajax.
In my create.js.erb file, I have this block of code that hides the paragraph:
$("#answers").append("<%= j render #answer %>");
tinyMCE.activeEditor.setContent('');
$(".hideAns").css("cssText", "display: none;");
In my delete.js.erb file, (This is where I am getting the Internal server error.) I have this block of code that checks whether the question has any answers or not:
$("#answer_<%= #answer.id %>").remove();
<% if #questions.answers.any? %>
console.log("has answers");
<% else %>
$(".hideAns").css("cssText", "display: block;");
<% end %>
Why is it not working? Am I not allowed to put an if statement inside a .js.erb file?
EDIT
Server log:
ActionView::Template::Error (undefined method `answers' for nil:NilClass):
1: $("#answer_<%= #answer.id %>").remove();
2:
3: <% if #question.answers.any? %>
4: console.log("has answers");
5: <% else %>
6: $(".hideAns").css("cssText", "display: block;");
7: <% end %>
Answer was to simply define the instance variable in the destroy method.
The fix:
def destroy
#question = Question.find(params[:question_id])
#answer.destroy
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end

Why is everything in my database (create and update times, topic_id, post_id) displaying in my view?

I'm new to programming and have been learning Ruby on Rails for about 6 weeks. I've added commenting functionality to my app, and while comments are being displayed properly, so is everything else in the (sqlite3) database associated with the comment - created_at, updated_at, comment_id, post_id.
The partial that displays comments has the following code:
<%= form_for [post, comment] do |f| %>
<p><%= #comments.each do |comment| %></p>
<small>
<p><%= comment.body %></p>
</small>
<% end %>
<% end %>
As you can see, I'm only trying to display the comment body, but I'm displaying everything.
Here is the create method from the comments controller:
def create
#post = Post.find(params[:post_id])
#comment = current_user.comments.build(params_comment)
#comment.post = #post
authorize #comment
if #comment.save
flash[:notice] = "Comment was created"
redirect_to [#post.topic, #post]
else
flash[:error] = "Comment failed to save"
redirect_to [#post.topic, #post]
end
end
end
I'm not sure why everyting is displaying if I'm only calling .body on comment. I've researched this problem but haven't found anything. Any help would be appreciated.
Here is the fix :-
<%= form_for [post, comment] do |f| %>
<!-- Here I removed `=` from `<%` %> -->
<p><% #comments.each do |comment| %></p>
<small>
<p><%= comment.body %></p>
</small>
<% end %>
<% end %>
#each returns the collection when the block is finished with full iteration. Now, you used <%= ..%>, which then printing the return value of #each. But if <%..%>, it wouldn't print although the #comments.each still returning the #comments collection.

nested attribute pagination error (kaminari)

I'm pretty sure that this is a simple fix but I'm not seeing it. I have an app where I'd like to show a music_videos comments. Below are my controllers:
def show
#music_video = MusicVideo.find(params[:id])
#comment = Comment.new
#comments = #music_video.comments.page(params[:page]).per(3)
end
The above is my music video controller.
def create
#music_video = MusicVideo.find(params[:music_video_id])
#comment = #music_video.comments.build(comment_params)
if #comment.save
flash[:notice] = "Comment Submitted"
redirect_to music_video_path(#music_video)
else
render 'music_videos/show'
end
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to root_path, notice: "Comment Deleted"
end
private
def comment_params
params.require(:comment).permit(:body)
end
Above is my comments controller
Finally my show page:
<div class="comments_row">
<% #music_video.comments.each do |comment| %>
<% if user_signed_in? && current_user.admin? %>
<p class="comment"><%= comment.body %></p>
<%= link_to 'Delete Comment', music_video_comment_path(#music_video,comment),
method: :delete %>
<% else %>
<p class="comment"><%= comment.body %></p>
<% end %>
<%end%>
</div>
<%= paginate #comments %>
I'm pretty sure something is wrong with my controllers, but I'm not sure exactly what it is. #comments is in the correct controller (MusicVideo) within the correct CRUD operation (show). Currently I have six comments in a particular show page and the pagination shows up just fine but the six comments are not paginated. Any thoughts?
EDIT-------------
I figured out one the problem but stumbled on a new one. I figured out that in my controller I am declaring #comments = pagination etc. etc. when in my views there is no #comments to paginate. The problem is now that when I use
<%= paginate #comment %>
the code will break.the problem now that I'm having is what variable to paginate. Trying this code will also break
<%= paginate #music_video.comments %>
Any recommendations?
I set up a test application using the kaminari gem for pagination. This is what my my music video controller's show action looks like:
def show
#music_video = MusicVideo.find(params[:id])
#comments = #music_video.comments.page(params[:page]).per(3)
end
And here is what my show view looks like:
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong> <%= #music_video.name %>
</p>
<% #comments.each do |comment| %>
<p>
Comment: <%= comment.text %>
</p>
<% end %>
<%= paginate #comments %>
<%= link_to 'Edit', edit_music_video_path(#music_video) %> |
<%= link_to 'Back', music_videos_path %>
It is working and the pagination is showing up for me.
I think one thing i see directly is that you should use <% #comments.each do |comment| %> instead of <% #music_video.comments.each do |comment| %> because the way you have it now it will display all comments for the video regardless of what page you are on. If you had 6 comments and wanted 3 per page you would see the pagination with the two pages because you're running your pagination based off of #comments and you would end up seeing all 6 comments on both pages because you're doing your .each with #music_videos.comments.each.
So, at least using #comments in both places would be a start. And make sure you're using <%= paginate #comments %> for the pagination. If you use this in your controller and view what do you get? Do you see any comments?
Also, Ryan Bates has a great screencast on Kaminari as well: http://railscasts.com/episodes/254-pagination-with-kaminari (that site is a great resource for rails questions)

Resources