I have a partial (_car_grid.html.erb) as follows:
<ul class="car-grid">
<%= render #cars %>
</ul>
Then I wish to call the partial from elsewhere but the instance var I am using is called #car_results. Is there a way to pass in #car_results and have it act as #cars inside the partial?
I have tried:
<%= render 'shared/car_grid', locals: {cars: #car_results} %>
But it doesn't seem to like it.
Any ideas?
You're close. Drop the '#' in your partial so that #cars becomes cars. When you pass in locals to a partial the partial receives local variables, not instance variables.
This means you'll need to change your other invocation of the partial as well to this:
<%= render 'shared/car_grid', locals: {cars: #cars} %>
In your partial, do not use the instance variable. Philip's suggestion is correct.
However, another thing I noticed in your code is that you are using the wrong syntax for rendering the partial. Actually, there are two ways for rendering partial
<%= render partial: "shared/car_grid", locals: {cars: #car_results} %>
or
<%= render "shared/car_grid", cars: #car_results %>
Your code does not contain partial keywords, so you will not need to use locals
Partials
By their nature, Rails partials are not meant to take #instance variables. They are meant to be used in any part of your application, hence why you need to pass local variables to them:
<%= render partial: 'shared/car_grid', locals: { cars: #car_results } %>
A partial is essentially like a code block - where local variables are referenced. This means inside the partial, you'll have to call a local variable, as defined when calling the partial:
#app/views/shared/_car_grid.html.erb
<% cars.each do |car| %>
<%= car.name %>
<% end %>
--
Collections
Some other interesting functionality you should know about is the use of collection when calling a partial.
<%= render partial: "shared/car_grids", collection: #car_results, as: :car %>
This basically works like an each loop - giving you the ability to reload the partial again & again for each member of the collection
Related
I've tried to make sense of layouts but got lost..Also googled & looked at other similar questions on SO but none of them helped.
Say I have MVC's (scaffold'ed) for A and B, creating their ..views/A/index.html.erb and ..views/B/show.html.erb among the rest.
A's index method sets a #a_collection.
Within B's show view I want to:
<p>..stuff for B..</p>
<%= render A's index %>
<p>..some more B-stuff</p>
How can I render A's index in that place in B's show?
You don't typically render a view inside of another view. You use partials to share code across views. For example:
# app/views/products/_product.html.erb
# this is the code you want to reuse
<p>Product Name: <%= product.name %></p>
# app/views/products/index.html.erb
<%= render #products %>
# app/views/stores/show.html.erb
<h1><%= #store.name %></h1>
<h2>Our Products</h2>
<%= render #store.products %>
<%= render #products %> is shorthand for <%= render partial: "product", collection: #products %>.
This is just the implicit rendering - in many cases you'll want to add more partials and render them explicitly. Like for example the _form.html.erb partial that you'll find in the scaffolds thats used to share a form between the create and edit views.
Think of partials like the view equivilent to a function - ideally they should take some input in the form of locals and result in a chunk of HTML.
the following view
<% #packageoffers.each do |packageoffer| %>
<% if #packageoffers_mss.include?(packageoffer) %>
<% elsif #availables.include?(packageoffer) %>
<%= render 'packageoffer', collection: #packageoffers %>
is returning an NameError undefined local variable or method 'packageoffer' when trying to process the partial _packageoffer.html.erb upon a line like the second taht follows:
<% item_sale_price = #item_price.sale_price * params[:quantity].to_i %>
<% markup_price = ((item_sale_price + (packageoffer.price * #r * #q)) * (1 + (#user.markup.to_d / 100) ) ) %>
note: #item_price is itself an item of an array section and had to be declared as an instance variable to pass it along <% #item_price = #allotments.select{ |a| a.section_id == section.id }.first
Thus, notwithstanding following the rails documentation guidelines,
I cannot process the array's item. Where lies the mistake?
You're using collection rendering incorrectly.
Your line...
<%= render 'packageoffer', collection: #packageoffers %>
Renders a single partial, and passes a local variable called collection with a value of #packageoffers.
The line you've written is a shorthand for:
<%= render partial: 'packageoffer', locals: { collection: #packageoffers } %>
If you want to render the entire collection and provide a partial name, you cannot use the render shorthand, you must use the explicit version of render partial:...:
<%= render partial: 'packageoffer', collection: #packageoffers %>
That said, it seems like your intent is to iterate over the collection, and conditionally render some items from it. In this case, you should not be using collection rendering at all, you should just use <%= render packageoffer %> to allow Rails to render the singular _packageoffer partial for each record.
Is the model called Packageoffer or PackageOffer? I think your problem is that Rails tries to infer the name of the variable from the model name. Can you try if there's a packge_offer?
If the model is PackageOffer, then you should use _package_offer as the partial name, package_offer as the variable name and also #package_offers. To be consistent with Rails conventions.
EDIT: if that's the problem, you can use your code with an as: :packageoffer option on the render to tell rails the name to use
Simple example:
index.html.erb:
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I can refactor this and move content to the _post.html.erb partial:
index.html.erb:
<%= render #posts %>
_post.html.erb:
<%= post.title %>
So how Rails passes attributes of every post without creating a block?
My posts_controller index action has only #posts = Post.all defined.
I thought that maybe by the name of the partial (post), but looks like its another Rails convention (plural and singular naming). Is it?
Many thanks for sharing!
Rails determines the name of the partial to use by looking at the model name in the collection. The full syntax to render a collection is as follows:
<%= render partial: "post", collection: #posts %>
However there is a shorthand for this:
<%= render #posts %>
According to docs:
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
this case, the partial is _post, and within the _post partial, you can
refer to post to get the instance that is being rendered.
You may find detailed explanation in rails guides
Rails 4.2
I have a collection displaying from a partial - is there a way to add a fragment of code in after a certain number in the collection?
So I have a 10 blog posts being shown in a list, each post's formatting from the partial list. I'd like to insert my AdSense code after every 3 posts
<%= render partial: "list", collection: #posts %>
Is there a way to do that automatically, or would I have to do something like assign a numbered id to each post and have "if (id/3) % 1 == 0", and conditionally display it?
Well inside the partial _list.html.erb, you can do check the counter variable provided by Rails list_iteration. So your check will be inside the _list.html.erb partial as:
render 'ad' if list_iteration.index % 3 == 0
You can also use list_counter helper.
Read this Rendering a collection of partials
<%= render partial: "ad", collection: #advertisements %>
This will render “advertiser/_ad.html.erb” and pass the local variable ad to the template for display. An iteration object will automatically be made available to the template with a name of the form partial_name_iteration. The iteration object has knowledge about which index the current object has in the collection and the total size of the collection. The iteration object also has two convenience methods, first? and last?. In the case of the example above, the template would be fed ad_iteration. For backwards compatibility the partial_name_counter is still present and is mapped to the iteration's index method.
Something like:
<% #posts.each_slice(3) do |posts| %>
<%= render partial: "list", collection: posts %>
<%= render partial: 'ad_sense' %>
<% end %>
Might work
each_slice docs for further reading
You could do something with the loop index like
<% #posts.each_with_index do |post, index| %>
<%= render partial: 'list', locals:{post: post} %>
<% if index % 3 == 2 %>
#adsense code here
<% end %>
<%end %>
I have a resource called Exercises in my application. I currently have a partial called _exercise.html.erb that I use to render them. I have an outlying case where I'd like to render them in a much different way. Can I make another partial for exercises that has this other format and still be able to use <%= render #exercises %>?
If not what is the best approach? Should I out a variable in the controller that tells the partial which layout to use, this would have both layout in one file and one if to decide. Or is there some better way?
If you'd like to use business logic to determine when to show what partial for your #exercises collection you should use the to_partial_path method in the Exercise model to define that. See #4 in this post: http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/
Or, if this is more of a view-related decision (i.e. one view will always use the regular _exercises.html.erb and another view would always use e.g. _alternate_exercises.html.erb) then you can specify as such:
<%= render partial: 'alternate_exercises', collection: #exercises, as: :exercise %>
This will render the _alternate_exercises.html.erb partial once for each item in #execrises passing the item in to the partial via a local_assign called exercise.
In this case, I suppose you have two options:
1) Put the conditional code inside of _exercises.html.erb
eg.
<% if #exercise.meets_some_condition %>
you see this stuff
<% else %>
you see other stuff
<% end %>
This way, you can still make use of <%= render #exercises %>
2) Otherwise, your other option is to have separate partials and render them outside.
eg.
<% #exercises.each do |exercise| %>
<% if exercise.meets_some_condition %>
<%= render "exercises/some_condition_exercise" %>
<% else %>
<%= render "exercises/exercise" %>
<% end %>
<% end %>
This is the best approach for rendering partial. You can wrap that partial with if else statement in your code. Here is my example
rendering with form called _victim.html.erb
<%= render :partial => "victim", :locals => {:f => f }%>
rendering without form
<%= render :partial => "victim"%>