63

I am rendering a partial like this:

$("#box_container").html("<%= escape_javascript( render :partial => 'contacts/contact_tile', :collection => @contacts) %>")

Problem is that my partial is expecting the variable 'contact'.

ActionView::Template::Error (undefined local variable or method `contact'

I simply want to tell the partial to expect a variable contact. Should iterate through @contacts as contact. How do I do that?

4 Answers 4

145

Found this is also helpful from the docs. You aren't limited to having the variable named after the partial:

http://guides.rubyonrails.org/layouts_and_rendering.html

To use a custom local variable name within the partial, specify the :as option in the call to the partial:

<%= render :partial => "product", :collection => @products, :as => :item %>

With this change, you can access an instance of the @products collection as the item local variable within the partial."

Sign up to request clarification or add additional context in comments.

3 Comments

this is strangely not working for me in Rails 4.1. Was it added in 4.2 or something?
This works, but only if you specify partial:. You cannot do render "product", collection: @projects, as: :item. You need to specify partial: "product" or the as option isn't applied.
@coreyward is correct, confirmed by Rails documentation: If you're not going to be using any of the options like collections or layouts, you can also use the short-hand defaults of render to render partials. for at least 5.1.3.
17

The documentation at http://guides.rubyonrails.org/layouts_and_rendering.html says:

When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial.

So it will be passed a variable called "contact_tile" instead of "contact". Perhaps you can just rename your partial.

If this naming is important, you could do it explicitly without the collection option by something like:

@contacts.each { |contact| render :partial => 'contacts/contact_tile', :locals => {:contact => contact } }

(although as a commenter pointed out, this may not be as performant)

4 Comments

see below answer. it's easy to override this behavior by overriding the name of the variable with the :as option.
You could simply write render @contacts, convention over configuration, you know. @contacts is an array of Contact instances, so every contact record returns 'contacts/contact' on to_partial_path invocation (Rails does this under the hood). api.rubyonrails.org/classes/ActionView/…
Your code example will parse and compile the template N times, and may slow down your site.
@dskecse , I think you could change your comment to a post answer.
16

Latest syntax are :

index.html.erb

<%= render partial: "product", collection: @products %>

_product.html.erb

<p>Product Name: <%= product.name %></p>

@products is used in partial as product

Where @products can be considered as Product.all and product can be considered as a row of product i.e. Product.first as looped all product one by one.

1 Comment

NOTE: You can't use a symbol for the partial value, like :product. You need to use a String, like you have it "product". I learnt that the hard way and it ended up defaulting to the model partial of the collection instead of the custom partial I wanted.
3

You can specify a custom variable name as the default with the keyword as:

<%= render partial: 'line_items/line_item', collection: order.line_items, as: :item %>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.