Partial rendering performance with parameter in rails - ruby-on-rails

I have a collection and want to iterate and render a partial:
<% #programs.each do |program| %>
<%= render "program", link: program_path(program) %>
<% end %>
For each rendering, I will pass a parameter called link. And it varies based on different situation.
program_path(program)
admin_program_path(program)
program.external_link
However, it will spend a huge time to render every partial, so it's a N+1 problem. I also tried to render collections but I don't know how to pass the parameter.
Does anyone know a better way to do it? Or shall I give up partial and put those code to every page which rendering the partial?
Cheers

You could use:
<%= render #programs %>
And create:
views/programs/_programs.html.erb
Then you choose the link with a condition in the partial.

Related

Rails: How to I render an existing view in another view?

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.

Rails Partials For Resources

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

Ruby on Rails does not display the right Partial

In my patient show view i have a part that refers to a partial
<h2>Anamnesen</h2>
<%= render #patient.anamneses %>
So i also created an partial in views/anamneses/ called _anamnese.html.erb
<p>
<b>Beschreibung:</b>
<%= anamnese.beschreibung %>
</p>
Now, my problem is that only Beschreibung: can be seen, the <%= anamnese.beschreibung %> is somehow blank! So maybe someones gues what i made wrong!
You need to pass variables explicitly by locals option for the partials to know it.
In the first template
render partial: 'anamneses/anamneses', locals: {anamneses: #patient.anamneses}

Render rails partial multiple times on same page

I have a partial that I'm rendering twice on the same page, but in two different locations (one is shown during standard layout, one is shown during mobile/tablet layout).
The partial is rendered exactly the same in both places, so I'd like to speed it up by storing it as a variable if possible; the partial makes an API call each time, and the 2nd call is completely unnecessary since it's a duplicate of the first API call.
Is there any way to store the HTML from the returned partial as a variable and then use that for both renders?
Edit: I'm hoping to do this without caching, as it is a very simple need and I'm looking to keep the codebase lean and readable. Is it possible to store the partial as a string variable and then reference that twice?
<% content_for :example do %>
<%= render :your_partial %>
<%end%>
then call <%= yield :example %> or <%= content_for :example %> wherever you want your partial called.
One option would be to use fragment caching. After you wrap the partial with a cache block, the second call should show the cached version of the first. For example:
<% cache do %>
<%= render(:partial => 'my_partial') %>
<% end %>
... later in the same view ...
<% cache do %>
<%= render(:partial => 'my_partial') %>
<% end %>
To store the result of the render to a string, you could try the render_to_string method of AbstractController. The arguments are the same as for render.
partial_string = render_to_string(:partial => 'my_partial')
I'm adding an answer to this old question because it topped Google for a search I just made.
There's another way to do this now (for quite a while), the capture helper.
<% reuse_my_partial = capture do %>
<%= render partial: "your_partial" %>
<% end %>
<div class="visible-on-desktop"
<%= reuse_my_partial %>
</div>
<div class="visible-on-mobile"
<%= reuse_my_partial %>
</div>
This is simpler and slightly safer than using content_for because there is no global storage involved that something else might modify.
The rails docs linked to use instance #vars instead of local vars because they want it to be available to their layout template. That's a detail you do not need to worry about, because you're using it in the same template file.

How do I use link_to_remote to pass then render a partial in rails?

I want to create several link_to_remote links that are campaign names:
<% #campaigns.each do |campaign| %>
<!--link_to_remote(name, options = {}, html_options = nil)-->
<%= link_to_remote(campaign, :update => "campaign_todo",
:url => %>
<% end %>
I want the output to update on the page to render a partial, which runs a loop through the values associated with the campaign.
The API docs says this will render a partial, but I'm not clear where the name of the :partial template is passed in, either here or in the controller
Thanks.
The controller would render the partial, according to the docs.
Usually, the result would be a partial prepared by the controller with render :partial.
of course in the controller. Here you create an AJAX snippet that will pull an url you specify from your controller.
generated javascript has no access to any partials b/c it runs on client PC.
and controller decides WHAT to respond to this request. it can render a partial, a template, a text, or anything.

Resources