Render partial :collection => #array specify variable name - ruby-on-rails

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?

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."

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)

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.

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 %>

Related

Rails How to use multiple variable on same class in one view

I'm trying to use multiple instance of the same class in a view with rails.
Basically i need to show a Branch with all its attributes and in the same page i have a form_for that need an empty Branch object. The problem is that when i create the empty Branch instance in the controller "#newBranch" the view can't access the first one anymore
here what I do in the controller:
def show
#customer = Customer.find(params[:id])
#branches = #customer.branches
#newBranch = #customer.branches.new #this is for the form_for
#newContact = #newBranch.build_contact #this is for the fields_for
end
if i try to use a singular item of the collection #branches for example:
<div class = "branch_container">
<%= render :partial => "customers/branch", :collection => #branches %>
</div>
and then inside the branch partial:
<%= branch.contact.name %>
i have the message:
"undefined method `name' for nil:NilClass"
All the models associations work fine and if i don't instantiate #newBranch and #newContact the problem disappear.
Basically i need to use two instance of the same Class (for example "#branches" in one partial and "#newBranch" in another one) in the same view.
What could be the solution?
Thank you.
Provide those instances as local vars:
<%= render :partial => "customers/branch", :collection => #branches, :locals => {:branch => #branch, :customer => #customer} %>
Oops didn't read well. For a new branch, contact is not set, so nil. Just check for this situation.
<% if branch.contact %>
_Your code_
<% else %>
No contact assigned
<% end %>
At the end i created #newBranch and #newContact in the view inside the form in the following way:
<%= form_for(newBranch = Building.new, :html => { :multipart => true }) do |building_form| %>
<% newBranch.build_contact %>
etc... etc...

Rails partial collection empty?

I've been trying to figure this one out for about an hour now. I have a partial collection that is indeed populated with member model objects, and when I try to render it using collection:
<%= render :partial => 'list', :collection => #members %>
In my _list.html.erb the #member_id and #member_email attributes are empty in the rendered html:
<%= check_box_tag('selected_member[]', #member_id, false) %>
<%= #member_email %>
The view renders correctly and I get 3 member items, but with the id and email blank.
What am I doing wrong? If I try to access the partial member using "member_id" or "member.id" I get "undefined local variable or method `member'", so clearly that's not the correct notation.
Now I've seen a bunch of different examples, but the collection method is the way I need to go. I need the partial to only deal with each member as the parent view has support for grouping members in different ways. If I implement a loop in the partial for each member, I'll have to move the grouping view code into it as well, which interacts with input fields in the parent view. e.g. it would be a mess to maintain.
Thanks in advance.
When you do:
<%= render :partial => 'list', :collection => #members %>
Rails is expecting the local variable within the partial file to be named the same as the partial file itself, in this case list.
So instead of member, by default it would be list like this:
<%= check_box_tag('selected_member[]', list.id, false) %>
<%= list.email %>
If you want the local variable to instead be named member, you should either rename the partial file or use this syntax:
<%= render :partial => 'list', :collection => #members, :as => :member %>
More info here (Sec. 3.4.5): http://guides.rubyonrails.org/layouts_and_rendering.html

Rails partial's local variable doesn't get set

I'm confused with passing a controller's instance variable to a partial template (named after this instance variable).
Documentation from http://api.rubyonrails.org/classes/ActionView/Partials.html says:
By default PartialRenderer uses the template name for the local name of the object passed into the template. These examples are effectively the same:
<%= render :partial => "contract", :locals => { :contract => #contract } %>
<%= render :partial => "contract" %>
But in my case I can't get the same magic.
ProductsController#show:
#foo = "123456789"
show.html.erb in the following edition works (controller's #foo appears as local variable foo in the _foo.html.erb):
<%= render :partial => 'foo', :locals => { :foo => #foo } %>
But next code doesn't pass the controller's #foo variable to the _foo.html.erb partial:
<%= render :partial => 'foo' %>
Why so?
As far as I am aware, locals usually have to be passed explicitly to the partial. The only case in which it may be passed automatically is when you're passing the main object for that controller action, i.e. if you are passing the record #foo in some action for the foos controller.
In your specific case, passing #product should work automatically. If you want to pass #foo, you'll need to pass it explicitly.

Using scope with a view partial

I have been using a scope to present some information to show todos that have been completed and are 24 hours old
scope :completed, joins(:user).where(:todos => { :complete => true })
scope :logged, completed.where("todos.updated_at <= ?", 1.day.ago)
Using the regular todo partial
<%= render #user.todos.logged =>
However I want to present those logged items in a different partial _logged.html.erb. I just can't figure out the proper way to pass scope results to a specific partial.
Thanks
Well, if you want to render partial for each item, yo can do:
<%=render :partial=> 'logged', :collection=>#user.todos.logged %>
Or if you want to pass the whole array to one instance then you can do
<%=render :partial=> 'logged', :object=>#user.todos.logged %>
In both cases I guess your object will be called logged.
Assuming that your partial contains <%= logged.title %> you want to render for each item, so you can use the first version.
First, to keep my conscience clean, let me say that that passing model code to your views is never a good idea. But if you insist :
<%= render :partial => 'some_partial',
:locals => {:some_variable => "somevalue",
:some_other_variable => some_other_variable} %>

What is the difference between render :object and :collection?

Is it
#cart have to put in :object ?
#cart.item have to put in : collection ?
Using :collection will run the partial once for every item in the array. While you're in the partial, the name of the object will be the name of the partial. So if you have:
<%= render :partial => 'cart', :collection => #carts %>
Then in your partial (_cart.html.erb, for example) you can use the cart object:
Cart Name: <%= cart.name %>
Here's a link to the documentation:
http://guides.rubyonrails.org/layouts_and_rendering.html

Resources