I'm trying to follow Ryan Bates Polymorphic association tutorial in order to put some comments to my site.
The thing is I have nested resources:
#Nesting Resources
resources :users do
resources :photos do
resources :comments
resources :tags
end
end
So I'm getting an error in my view (photos/show)
undefined method `each' for nil:NilClass
I suppose the problem is in my controller, with comments, that is not defined correctly, but since I have nested resources, I don't know how to do it.
Photos Controller
def show
#photo = Photo.friendly.find(params[:id])
#user = #photo.user
#commentable = #photo
#comments = #commentable.comments
#comment = Comment.new
end
New Comment Partial
<h2>Comments</h2>
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
TodavĂa no hay comentarios
<% if user_signed_in? %>
<%= render "comments/form" %>
<% end %>
<% end %>
Form partial (comments/form)
<%= form_for [#commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_area :content, rows: 8 %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Comments partial (comments/comments)
<div id="comments">
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
Your error says undefined method each for nil:NilClass. As you can guess you are calling each on a nil object. Here your #comments is nil and hence giving your trouble.
In your view try something like this:
<div id="comments">
<% if #comments %>
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
<% end %>
</div>
Edit:
So if you look at your code you have #comments till here:
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
#do stuff
<% end %>
it's after you call your partial that your #comment is lost so try this:
<% if #comments.any? %>
<%= render "comments/comments", comments: #comment %>
<% else %>
#do stuff
<% end %>
and then in your view use
<div id="comments">
<% comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
Related
I'm working on a kind of blog and would like the render a partial from my controller if a condition is true.
This is my controller method:
def comments_session
render partial: 'comments/form' if signed_in?
render partial: 'comments/show'
end
And this is my view:
<%= comments_session %>
These are my partials:
_show.html.erb
<% #post.comments.sort_by(&:created_at).reverse.each do |comment| %>
<div class="col-lg-12 mt-3 pt-3 border-top">
<% if signed_in? %>
<% if current_user.username == comment.user.username %>
<%= link_to 'Excluir', post_comment_path(#post, comment), :class =>"btn btn-sm btn-danger btn_round float-right border-dark",
method: :delete, data: {confirm: "Deseja realmente excluir esse comentário?"} %>
<% else %>
<% end %>
<% else %>
<% end %>
<h6><strong>~ <%= comment.user.username %></strong></h6>
<p class="comment"><%= comment.body %></p>
<p class="lead distance_of_time"><small>
<%= time_ago_in_words(comment.created_at) %>
</small></p>
</div>
<% end %>
and _form.html.erb
<%= form_with(model: #comment, url: [#post, #comment], local: true) 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 |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="col-lg-10 form-group">
<%= f.text_area :body, :class =>"form-control", :placeholder =>"Escreva o Que Quiser!" %>
</div>
<div class="col-lg-1 form-group">
<%= f.submit "Comentar", :class =>"btn btn-lg btn-primary border-dark text-light" %>
</div>
</div>
<% end %>
The method renders "_show.html.erb" perfectly, but doesn't do the same with the other...
I tried to change and remove the condition, but it didn't work :/
Please, I'd like to know why I can't render it
Thanks!
Rails is not allowed to render more than one partial in controller.
def comments_session
if signed_in?
render partial: 'comments/form'
else
render partial: 'comments/show'
end
end
Can you try this way?
def comments_session
return render partial: 'comments/form' if signed_in?
render partial: 'comments/show'
end
I think you're getting a DoubleRenderError or something like that
I'm making a bloglike application. I want to make it so that blog posts are editable if clicked.
This is my partial that displays all the posts of a user and makes them clickable
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3, false).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= link_to edit_post_path(feed) do %>
<%= render feed %>
<% end %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
This is the Edit view that it redirects to when a post is clicked:
<% if logged_in? %>
<div class="row">
<%= render 'shared/post_form' %>
</div>
<% end %>
And this is the '_post_form' partial which is the layout for an editable post:
<%= form_for(#post) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new post..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
When I click a post to edit it it does redirect however it gives me the error: "First argument in form cannot contain nil or be empty"
Any suggestions on how to resolve this?
In your controller's edit method you have to set #post like,
def edit
#post = Post.find(params[:id])
end
I've been looking for the same problem but not found it.
I'm following this guide, and I'm stuck on setting validations for the text field.
Model (article.rb):
class Article < ActiveRecord::Base
validates :title, presence: true, length: { minimum: 5 }
end
Controller:
class ArticlesController < ApplicationController:
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
private
def article_params
params.require(:article).permit(:title, :text)
end
View (new.html.erb):
<%= form_for :article, url: articles_path do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', articles_path %>
And when I try to add a new article I open http://localhost:3000/articles/new but instead of the form I see error undefined method errors' for nil:NilClass because of the error in this line <% if #article.errors.any? %>
What am I missing here. Looks like #article is being validated before created? How can I fix it?
index.html.erb:
<h1>Listing articles</h1>
<%= link_to "New article", new_article_path %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
</tr>
<% end %>
</table>
You need to call:
<%= form_for #article, url: articles_path do |f| %>
In the first line of new.html.erb
Change the form_for to
<%= form_for(#article) do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
........
<% end %>
articles_controller.rb
class ArticlesController < ApplicationController
....
end
I have a form with a nested object something like this:
<%= form_for(#person) do |f| %>
<% if #person.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#person.errors.count, "error") %> prohibited this record from being saved</h2>
<ul>
<% #person.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= render 'person_fields', f: f, :person => #person %>
<%= f.fields_for :posts do |builder| %>
<%= render 'post_fields', f: builder %>
<% end %>
<br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The thing is the validation error messages come up in the format {attribute}{message}, i.e the regular full_messages format. The {attribute} also includes the model name which isn't what I want, I just want to display the attribute and the message.
I'm thinking I can potentially us the rails internationalisation api but could use some guidence; has anyone else managed to do this?
I worked out how to this... just for reference, here's my solution:
<%= form_for(#person) do |f| %>
<% #person.errors.messages.each do |msg| %>
<% msg[1].each do |m| %>
<% if msg[0].to_s.split(".")[-1] == "base" %>
<li><%= m %></li>
<% else %>
<li><%= msg[0].to_s.split(".")[-1].humanize.titlecase %> <%= m %></li>
<% end %>
<% end %>
<% end %>
<%= render 'person_fields', f: f, :person => #person %>
<%= f.fields_for :posts do |builder| %>
<%= render 'post_fields', f: builder %>
<% end %>
<br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I've used the custom-err-msg plugin in the past and had a lot of success.
Here is my show.html.erb file.
<% provide(:title, #user.name) %>
<div class="row">
<aside class="span4">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
<section>
<%= render 'shared/stats' %>
</section>
</aside>
<div class="span8">
<%= render 'follow_form' if signed_in? %>
<% if #user.microposts.any? %>
<h3>Microposts (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
_follow.html.erb partial file:
<%= 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 %>
_unfollow.html.erb partial file:
<%= 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 %>
And my _follow_form.html.erb partial:
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
Edit: I would also like to say that I'm using Bootstrap. When I inspect the user page, both classes span4 and span8 come up, but there is a complete blank where "follow_form" should be.
Edit: This question was answered years ago :)
i came across the same problem , you can rectify this by doing the following changes :
step 1)
In app/views/users/show.html.erb
change code from this :
<div class = "span8">
<%= render 'follow_form' if signed_in? %>
<% if #user.microposts.any? %>
to this:
<div class = "span8">
<%= render 'shared/follow_form' if signed_in? %>
<% if #user.microposts.any? %>
step 2)
In partial app/views/shared/_follow_form.html.erb
change the code from this :
<% unless current_user?(#user) %>
<div id="follow_form">
<%if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
to this :
<% unless current_user?(#user) %>
<div id="follow_form">
<%if current_user.following?(#user) %>
<%= render 'shared/unfollow' %>
<% else %>
<%= render 'shared/follow' %>
<% end %>
</div>
<% end %>