I am developing a webapp (well trying to) in Ruby on Rails.
I have a partial render in my index.html.erb
<%= render :partial => "houses/index", :locals => #houses %>
index.html.erb is loaded when the user hits the root of my domain. This partial cause this error:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
Extracted Source around line 8
5: <th>Washrooms</th>
6: </tr>
7:
8: <% #houses.each do |house| %>
9: <tr>
10: <td><%=h house.short_desc %></td>
11: <td><%=h house.bedrooms %></td>
Trace of template inclusion: app/views/home/index.html.erb
All I would like to is display 5 houses on my Homepage (index.html.erb)
What am I missing to get this to work?
Many thanks
EDIT:
Houses_controller
NoMethodError in Home#index
Showing app/views/houses/_index.html.erb where line #10 raised:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
Extracted source (around line #10):
7: Washrooms
8:
9:
10: <% #houses.each do |house| %>
11:
12: <%=h house.short_desc %>
13: <%=h house.bedrooms %>
Trace of template inclusion: app/views/home/index.html.erb
The value of :locals is supposed to be a Hash that defines local variables. So
<%= render :partial => "houses/index", :locals => {:houses => #houses} %>
and then
<% houses.each do |house| %>
To reiterate, since the new error you posted shows that you are still not doing it correctly:
If you're passing it through :locals, you want houses.each, not **#**houses.each. No snail. Local variables don't have a # prefix; instance variables do.
Locals takes a hash of local variables, like so:
<%= render :partial => "houses/index", :locals => { :houses => #houses } %>
Also, when you pass in a local variable to a partial, you should use it as a local variable rather than an instance variable within the partial, as so:
<% houses.each do |house| %>
# do stuff with each house
<% end %>
You don't need to pass it in :locals if it's an instance variable. Instance variables are available in all partials.
In your view:
<% #houses.each do |house| %>
# do stuff with each house
<% end %>
Related
Here is the code
Model:
Category has many subjects
View:
show:
<% category.subjects.each do |subject| %>
<div class="container">
<%= render partial: "layouts/trial", :locals => {:subject => subject} %>
</div>
<% end %>
layouts/trial:
<%= description(#subject) %>
trial_helper.rb
module TrialHelper
def subject
#subject ||= []
end
def description(subject)
#des = "#{subject.content}"
end
end
turn out
ActionView::Template::Error (undefined method `content' for nil:NilClass):
1: <%= description(#subject) %>
I've tried using
<%= render partial: "layouts/trial", :locals => {:subject => #category.subject} %>
and
def description(subject)
#des = "#{#subject.content}"
end
But it's still not work. What is the problem?
Probably your subject is nil in your layouts/trial.
The best approach is to debug and check where the problem is occurring.
You can set in your layouts/trial something like <%= raise #subject.inspect %> and if it really returns nil, we can confirm that this code here <%= render partial: "layouts/trial", :locals => {:subject => subject} %> isn't working as expected.
change
<%= description(#subject) %>
to
<%= description(subject) %>
locals are passed as local variables not instance variables
I've got this working now quite accidentally, but I don't understand what causes it to break when I explicitly specify what partials are to be used for rendering the resource/s. Can anyone explain it?
The index template for my Posts controller contained the following line, which was giving me an error:
<%= render partial: 'posts', collection: #posts %>
The error (in my browser) said:
NoMethodError in Posts#index
Showing /Users/applebum/Sites/rails_projects/eventful2/app/views/posts/_posts.html.erb where line #1 raised:
undefined method `any?' for #<Post:0x000001064b21f0>
Extracted source (around line #1):
1: <% if posts.any? %>
2: <div id="posts">
3: <% posts.each do |post| %>
4: <%= render partial: "posts/post", locals: { post: post } %>
Changing the problem line to
<%= render #posts %>
made the error disappear and the posts appear (displayed nicely in markup from the appropriate partials) as I had wanted and expected them to.
Here's my _posts.html.erb partial:
<% if posts.any? %>
<div id="posts">
<% posts.each do |post| %>
<%= render partial: "posts/post", locals: { post: post } %>
<% # render :partial => "comments/comments", :collection => post.comments %>
<% end %>
</div>
<% end %>
And the _post.html.erb partial it's referring to, if that matters:
<div class="post" id="post_<%= "#{post.id}" %>">
<div class="post_inner">
<%= link_to avatar_for(post.user, size: "small"), post.user.profile %>
<div class="post_body">
<div class="user-tools">
<% if can? :destroy, post %>
<%= link_to '<i class="fi-x"></i>'.html_safe, post, :method => :delete, remote: true, :class => "delete", :confirm => "Are you sure you want to delete this post?", :title => post.content %>
<% end %>
</div>
<h5 class="username">
<%= link_to post.user.name, post.user.profile %>
<span class="timestamp">• <%= time_ago_in_words(post.created_at) %> ago</span>
</h5>
<div class="content">
<%= post.content %>
</div>
<ul class="foot">
<li>Like<li>
<li>Share</li>
</ul>
</div>
</div>
</div>
And the relevant bits from the controller:
class PostsController < ApplicationController
respond_to :html, :js # Allow for AJAX requests as well as HTML ones.
before_filter :load_postable
load_and_authorize_resource
def index
#post = Post.new
#posts = #postable.posts
end
private #################
def load_postable
klass = [User, Event].detect { |c| params["#{c.name.underscore}_id"] } # Look for which one of these there's a ***_id parameter name for
#postable = klass.find(params["#{klass.name.underscore}_id"]) # Call find on that, passing in that parameter. eg Event.find(1)
end
Can anyone explain to me what's going on here? I couldn't find anything in the Layouts and Rendering guide at rubyonrails.org.
Thanks!
Your error comes from assuming :collection and #posts mean the same thing when rendering. From Rails Docs (point 3.4.5):
Partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection
So, if you use that, for each post, you will be doing post.any? which fails as any? isn't defined for a single post.
From the same docs, you should check if render returns Nil to see if the collection is empty:
<h1>Posts</h1>
<%= render(#posts) || "There are no posts." %>
PD: Use the partial to render only one post, not all of them.
GL & HF.
Right now I have a rails partial that looks like this:
<%= render :partial => "/talk/partials/comment", :collection => #comments, :locals => {:votes => #votes} %>
I am passing in a collection of comments and another local variable.
That comment partial then goes right into using the comment variable and works fine.
I have since made another partial called '/talk/partials/comment_2014'. When I try this, I am getting the error undefined local variable or method 'comment'. From what I can gather, when I have a different partial name, something with the variable also changes. I would like to keep the same comment variable for the new partial ''/talk/partials/comment_2014'. How would I go about doing this?
Something I tried which did not work was the following:
<% #comments.each do |comment| %>
<%= render :partial => "/talk/partials/comment_2014", comment: comment, :locals => {:votes => #votes} %>
<% end %>
which did not work either.
You can do it this way
<% #comments.each do |comment| %>
<%= render "/talk/partials/comment_2014", comment: comment, votes: #votes %>
<% end %>
Or
<% #comments.each do |comment| %>
<%= render partial: "/talk/partials/comment_2014", locals: { comment: comment, votes: #votes } %>
<% end %>
Notice in the second way the comment is inside the locals.
I have the following in a view (.html.erb) :
<% #posts = GetAllPostsFunctions %> (removed for berivity)
<% #posts.each do |post| %>
<%= post.title %>
<%= render :partial => "posts/post_show" %>
<% end %>
the posts_show partial has the following:
....
<td><%=h #post.title %> </td>
But I get the following error
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.title
Any ideas?
You can also simply things by using the :collection for render :partial. Which pass each item in the value for :collection to a local variable sharing the name of your partial.
<% #posts = GetAllPostsFunctions %> (removed for berivity)
<%= render :partial => "posts/post_show", :collection => #posts %>
In this case, Rails will render post_show for each item in #posts with the local variable post_show set to the current item. It also provides handy counter methods.
Successfully using this approach would require renaming the app/views/posts/_post_show.html.erb partial to app/views/posts/_post.html.erb to or changing every occurance of post in your partial to post_show. If you renamed the partial to the conventional _post.html.erb which will then allow you to simply do:
<%= render :partial => #posts %>
Which will render the partial for every single post in the #posts variable.
Since the post variable in the each loop is a locale variable you have to make it available to the partial:
<%= render :partial => "posts/post_show", :locals => {:post => post} %>
You can then access the title through the local variable post:
<td><%=h post.title %> </td>
You could also simplify the whole thing by rendering the posts as collection. Take a look at the Rails documentation for more information:
http://api.rubyonrails.org/classes/ActionController/Base.html#M000658
It doesn't look like you're setting the #post of the partial, so when it goes to evaluate the partial it gets a null reference.
Alternately, ensure that your post fetching functions are actually returning something
I'm not positive, but I think in the partial you have to do post.title not #post.title
Sorry if I misunderstood you, I'm new to rails.
I'm using the will_paginate plugin and I get the following error only when I'm running on a server rather than locally:
undefined method `total_pages' for []:Array
Extracted source (around line #8):
5: <% session[:page] = params[:page] %>
6: <h2>Previous Scenario</h2>
7: <% end %>
8: <%= will_paginate #scenarios, :next_label => 'Older', :prev_label => 'Newer' %>
9: <div class="box">
10: <% for scenario in #scenarios %>
11: <% #created = scenario.created_at %>
Any ideas?
Somehow, #scenarios is an ordinary Array for you and it can't be from Scenario.paginate() method because that one always returns a WillPaginate::Collection object.
Does your controller have the other half of the equation, e.g.
#scenario = Scenario.paginate(:page => params[:page]||1)
Alternatively I think you might have a plugin on the server side that is converting your Active Record set into a plain array. I'd need a bit more info to look at that.