Rails partial looping through local_assigns - ruby-on-rails

I'm populating a partial with many instance variables in the locals hash. Is there a way to pull multiple instance variables from local_assigns in the partial?
<%= render 'tabs', :locals => {:tab1 => #news, :tab2 => #people, :tab3 => #tags} %>
In the partial I'd like to create a dynamic set of tabs based on the number of instance variables I populate the locals with.
<% local_assigns.each do |local_assign| %>
<% local_assign.each do |tabs| %>
<!-- Grab tab class name -->
<li class="tab"><%= tabs[:class] %></li>
<% end %>
<% end %>

Why don't you just pass it as an array
render 'tabs', :locals => {:tabs => [#news, #people, #tags]} %>
in your view
<% tabs.each do |tab| %>
<!-- Grab tab class name -->
<li class="tab"><%= tab[:class] %></li>
<% end %>

Thanks Vimsha I ended up using collection instead of locals and created the instance variable in the controller.
http://guides.rubyonrails.org/layouts_and_rendering.html
Controller
#tabs = [#news, #people]
View
<%= render 'tabs', :collection => #tabs %>

Related

Passing instance variables in nested partials in Rails?

I am having difficulty passing instance variables in nested partials. Here is what I have done.
In controller Own:
def home
#item = "some values"
#ref = "some other values"
end
Then I have a home page "home.html.erb", in which I rendered "_product_table.html.erb":
<%= render "own/product_table", :item => #items, :ref => #ref %>
Then, in "_product_table.html.erb", I have to render "_product.html.erb":
<% #items.each do |item|%>
<%= render "own/product", :item => item, :ref => #ref %>
<% end %>
I can't understand why the ref variable is not available in the "_product.html.erb" partial.
You are passing ref as argument to the partial in home.html.erb, so in _product_table.html.erb you should use it similarly to item, not as instance variable:
<% #items.each do |item|%>
<%= render "own/product", :item => item, :ref => ref %>
<% end %>

Rendering a partial using specific controller variables

I am trying to play with Rails naming conventions as in here and render two different pages with different variables using one partial.
index
<%= render #events_future %>
current
<%= render #events_current %>
event controller
def index
#events_future = ...
end
_event.html.erb
<% #events.each do |event| %>
...
<% end %>
I get the undefined "each" method
Please point me in the right direction
I think the best thing to do here is to pass a locals to the partial _event.html.erb because the partial needs to display different objects like follows:
index
<%= render 'event', events: #events_future %>
current
<%= render 'event', events: #events_current %>
In the above two render statements, the events gets passed to the event partial as a local.
Then in your _event.html.erb you would do:
<% events.each do |event| %>
...
<% end %>
Do you have #events initialized in your controller?
I see that you have #events_future and #events_current, but if #events is not defined in the controller, your view wouldn't know what you are referring to.
If you want to reuse events for both future and current, use the following in each view
<!-- index.html.erb -->
<%= render 'event', events: #events_future %>
<!-- current.html.erb -->
<%= render 'event', events: #events_current %>
This renders the _event.html.erb partial and sets the events local variable. In _event.html.erb, use
<% events.each do |event| %>
<!-- do stuff -->
<% end %>
You have to pass the variable to the partial when you render it:
render :partial => 'event', :locals => {:events => #events_current} %>
render :partial => 'event', :locals => {:events => #events_future} %>
And then in your partial you do:
<% events.each do |event| %>
...
<% end %>

How can I display a list of child records?

I have a table of accounts and venues where an account can have many venues.
I'm displaying all the accounts as partials on the accounts index page and would like for each one to include the names of the venues linked to them.
Heres what I have:
account partial
<%= link_to free_account do %>
<div class="account_partial">
<span class="account_header"><%= free_account.name %></span> - <span class="free_account_highlight">(<%= free_account.role %>)</span><br>
<%= render :partial => 'venues/account_venue', :collection => #account.venues %>
</div>
<% end %>
account_venue partial
<%= venue.name %>
I'm getting this error:
NoMethodError in Accounts#index
undefined method `venues' for nil:NilClass
Extracted source (around line #12):
12: <%= render :partial => 'venues/account_venue',
:collection => #account.venues %>
Any help would be much appreciated!
edit
accounts_controller
class AccountsController < ApplicationController
load_and_authorize_resource
def index
#accounts = Account.all(:include => :venues)
end
end
accounts index.html.erb
<div id="narrow_container">
<div class="free_accounts_container">
<h2 class="show_orange">Free accounts</h3>
<%= render :partial => 'free_account', :collection => #accounts %>
</div>
<div class="premium_accounts_container">
<h2 class="show_orange">Premium accounts</h3>
<%= render :partial => 'premium_account', :collection => #accounts %><br><br>
</div>
<div class="clearall"></div>
<div class="button">
<%= link_to 'add account', new_account_path %>
</div>
</div>
_free_account.html.erb
<%= link_to free_account do %>
<% if free_account.role == "free" %>
<div class="account_partial">
<span class="account_header"><%= free_account.name %></span> - <span class="free_account_highlight">(<%= free_account.role %>)</span><br>
<div class="owner_details">
<span class="pre_account_highlight">Owners username:</span><span class="account_highlight"><%= free_account.user.username %></span>
<span class="pre_account_highlight">Owners e-mail:</span><span class="account_highlight"><%= free_account.user.email %></span>
</div>
<div class="account_details">
</div>
<%= render :partial => 'venues/account_venue', :collection => #account.venues %>
</div>
<% else %>
<% end %>
<% end %>
update
If I change the partial call to:
<%= render :partial => 'venues/account_venue', :collection => #accounts %>
and the account_venue partial to just read 'test' it loads without error but displays the word test 4 times (theres 4 account records) if I add a new account record it displays the word test 5 times.
You need to set #account to something in your controller, and that model instance should be joined to (or include) the Venues model. Like so:
#account = Account.find(params[:id], :include => :venues)
Edit: I take it you have already set up your Account and Venue models with has_many and belongs_to relationships?
Edit two: I see now that you're trying to access Accounts#index, in which case the code above should be changed to something like (since we're not looking at one specific account):
#accounts = Account.all(:include => :venues)
Edit three: Now that you've posted the controller and partials code as well, a couple of things stand out; When rendering a partial using a collection the resulting object inside the partial derives its name from the partial and not the collection. From the Rails Guides:
"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."
In your partial _account_venue.html.erb you have <%= venue.name %> - this needs to be changed to <%= account_venue.name %>.
Secondly, in _free_account.html.erb, where you call the account_venue partial, you're referring to a collection object named #account - where does this come from? Since the free_account partial is also called with a collection, the object you should be using will be called free_account - indeed you are referencing it by this name earlier in the same partial when you do <%= free_account.name %>. So the render partial call should look like this:
<%= render :partial => 'venues/account_venue', :collection => free_account.venues %>
Hope this helps!
Looks like your not assigning #account to anything. Should this be free_account instead?

An instance of a model to render into a partial

I render an instance of a model into a partial with the following code <%= render #places %>.
I created _places.html.erb. I thought I could use the following code since the render method is supposed to iterates trhough the places collection :
<li>
<%= link_to place.name, place %>
</li>
I get this error : undefined local variable or method 'place' for #<#<Class:0x007fc1c0a4e6b8>:0x007fc1c05050a8>
I have to use to make it work :
<% #places.each do |place| %>
<li>
<%= link_to place.name, place %>
</li>
<% end%>
try this:
<%= render :partial => 'places.html', :collection => #places, :as => :place %>
Or, if you have the partial file as singular name, you can do it like this(without the variable :as)
<%= render :partial => 'place.html', :collection => #places %>

Rails generate extra <li> tags automatically

this is the code :
<ul >
<% items.each do |item|%>
<%= render :partial => "somepartial", :locals => { :title => item.title} %>
test_text
<% end %>
</ul>
the partial:
<li><a><%= title %></a></li>
and the out put is :
<ul >
<li><a>item1</a></li>
<li>test_text</li>
<li><a>item2</a></li>
<li>test_text</li>
<li><a>item3</a></li>
<li>test_text</li>
</ul>
< li > tags around the test_text is extra. Partial and the model is not related, so do not suggest me to use collection method. When partial is rendered inside the each loop, rails does not put li tags around it, but the anything except the partial gets li tags around them.
The question is not entirely clear to me, so maybe i should refrain from answering.
But, i would propose to use haml, which gives you much cleaner views.
Your main view would become:
%ul
= render :partial => "items/item", :collection => items
and your partial items\_item.html.haml would look like this
%li
%a
= item.title
I don't see a real link inside your li-item, so maybe you want something like:
%li
= link_to item.title, item_path(item)
Instead of this:
<% items.each do |item|%>
<%= render :partial => "items/item", :locals => { :title => item.title} %>
<% end %>
Try this:
<%= render :partial => "items/item", :collection => items %>

Resources