class ActionView::PartialRenderer
Experimental RBS support (using type sampling data from the type_fusion
project).
# sig/action_view/renderer/partial_renderer.rbs class ActionView::PartialRenderer < ActionView::AbstractRenderer def find_template: (String path, Array[] locals) -> ActionView::Template def render: (String partial, #<Class:0x0000000131b3f510> context, nil block) -> ActionView::AbstractRenderer::RenderedTemplate end
As you can see, the :locals
hash is shared between both the partial and its layout.
</div>
Title: <%= chief.name %>
Budget: $<%= user.budget %>
<div id=“administrator”>
…this will return:
<% end %>
Title: <%= chief.title %>
<%= render(layout: “administrator”, locals: { user: chief }) do %>
<%# app/views/users/_chief.html.erb %>
You can also apply a layout to a block within any template:
as available in the partial.
available as local variables inside the layout template under the same names
The current object being rendered, as well as the object_counter, will be
</ul>
</li>
Name: Bob
<li>
</li>
Name: Alice
<li>
<ul>
Given two users whose names are Alice and Bob, these snippets return:
</ul>
<%= render partial: “user”, layout: “li_layout”, collection: users %>
<ul>
<%# app/views/users/index.html.erb %>
</li>
<%= yield %>
<li>
<%# app/views/users/_li_layout.html.erb %>
</ul>
<% end -%>
</li>
<%= render partial: “user”, locals: { user: user } %>
<li>
<% users.each do |user| -%>
<ul>
<%# This does not use layouts %>
<%# app/views/users/index.html.erb %>
Name: <%= user.name %>
<%# app/views/users/_user.html.erb %>
the collection. For example, these two snippets have the same output:
If a collection is given, the layout will be rendered once for each item in
</div>
Name: <%= user.name %>
Deadline: <%= user.deadline %>
<div id=“editor”>
Here’s the editor:
</div>
Name: <%= user.name %>
Budget: $<%= user.budget %>
<div id=“administrator”>
Here’s the administrator:
…this will return:
</div>
<%= yield %>
Deadline: <%= user.deadline %>
<div id=“editor”>
<%# app/views/users/_editor.html.erb %>
</div>
<%= yield %>
Budget: $<%= user.budget %>
<div id=“administrator”>
<%# app/views/users/_administrator.html.erb %>
Name: <%= user.name %>
<%# app/views/users/_user.html.erb %>
<%= render partial: “user”, layout: “editor”, locals: { user: editor } %>
Here’s the editor:
<%= render partial: “user”, layout: “administrator”, locals: { user: administrator } %>
Here’s the administrator:
<%# app/views/users/index.html.erb %>
of users:
specified globally for the entire action, but they work in a similar fashion. Imagine a list with two types
Partials can have their own layouts applied to them. These layouts are different than the ones that are
== Rendering partials with layouts
<%= render @posts %>
# <%= render partial: “posts/post”, collection: @posts %>
# that’s why we can replace:
# @posts is an array of Post instances, so every post record returns ‘posts/post’ on to_partial_path
,
<%= render @account %>
# <%= render partial: “accounts/account”, locals: { account: @account} %>
# @account.to_partial_path returns ‘accounts/account’, so it can be used to replace:
<%= render “account”, account: @buyer %>
# Instead of <%= render partial: “account”, locals: { account: @buyer } %>
<%= render “account” %>
# Instead of <%= render partial: “account” %>
defaults of render to render partials. Examples:
If you’re not going to be using any of the options like collections or layouts, you can also use the short-hand
== Rendering the default case
<%= render partial: @posts %>
# <%= render partial: “posts/post”, collection: @posts %>
# that’s why we can replace:
# @posts is an array of Post instances, so every post record returns ‘posts/post’ on to_partial_path
,
<%= render partial: @account %>
# <%= render partial: “accounts/account”, locals: { account: @account} %>
# @account.to_partial_path returns ‘accounts/account’, so it can be used to replace:
and pick the proper path by checking to_partial_path
method.
Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work
== Rendering objects that respond to to_partial_path
This will render the partial advertisement/_ad.html.erb
regardless of which controller this is being called from.
<%= render partial: “advertisement/ad”, locals: { ad: @advertisement } %>
Two controllers can share a set of partials and render them like this:
== Rendering shared partials
<%= render(partial: “ad”, collection: @advertisements) || “There’s no ad to be displayed” %>
to specify a text which will be displayed instead by using this form:
If the given :collection
is nil
or empty, render
will return nil
. This will allow you
<%= render partial: “ad”, collection: @advertisements, spacer_template: “ad_divider” %>
The following example will render advertiser/_ad_divider.html.erb
between each ad partial:
You can specify a partial to be rendered between elements via the :spacer_template
option.
The :as
option may be used when rendering partials.index
method.
For backwards compatibility the partial_name_counter
is still present and is mapped to the iteration’sfirst?
and last?
. In the case of the example above, the template would be fed ad_iteration
.
the collection and the total size of the collection. The iteration object also has two convenience methods,partial_name_iteration
. The iteration object has knowledge about which index the current object has in
iteration object will automatically be made available to the template with a name of the form
This will render advertiser/_ad.html.erb
and pass the local variable ad
to the template for display. An
<%= render partial: “ad”, collection: @advertisements %>
example in “Using partials” can be rewritten with a single line:
accepts an array and renders a partial by the same name as the elements contained within. So the three-lined
render a sub template for each of the elements. This pattern has been implemented as a single method that
The example of partial use describes a familiar pattern where a template needs to iterate over an array and
== Rendering a collection of partials
<%= render partial: “account”, locals: { user: @buyer } %>
This is equivalent to
<%= render partial: “account”, object: @buyer, as: ‘user’ %>
wanted it to be user
instead of account
we’d do:
With the :as
option we can specify a different name for said local variable. For example, if we
<%= render partial: “account”, locals: { account: @buyer } %>
equivalent to:
would provide the @buyer
object to the partial, available under the local variable account
and is
<%= render partial: “account”, object: @buyer %>
The :object
option can be used to pass an object to the partial. For instance:
By default ActionView::PartialRenderer doesn’t have any local variables.
== The :as
and :object
options
render advertiser/_ad.html.erb
and pass the local variable ad
to the template for display.
This would first render advertiser/_account.html.erb
with @buyer
passed in as the local variable account
, then
<% end %>
<%= render partial: “ad”, locals: { ad: ad } %>
<% @advertisements.each do |ad| %>
<%= render partial: “account”, locals: { account: @buyer } %>
In another template for Advertiser#buy, we could have:
This would render “advertiser/_account.html.erb”.
<%= render partial: “account” %>
In a template for Advertiser#account:
templates that could be rendered on their own.
follow the naming convention of being prefixed with an underscore – as to separate them from regular
single object (we call this kind of sub templates for partials). It relies on the fact that partials should
There’s also a convenience method for rendering sub templates within the current controller that depends on a
= Action View Partials
def find_template(path, locals)
Experimental RBS support (using type sampling data from the type_fusion
project).
def find_template: (String path, locals) -> ActionView::Template
This signature was generated using 1 sample from 1 application.
def find_template(path, locals) prefixes = path.include?(?/) ? [] : @lookup_context.prefixes @lookup_context.find_template(path, prefixes, true, locals, @details) end
def initialize(lookup_context, options)
def initialize(lookup_context, options) super(lookup_context) @options = options @locals = @options[:locals] || {} @details = extract_details(@options) end
def render(partial, context, block)
Experimental RBS support (using type sampling data from the type_fusion
project).
def render: (String partial, #<Class:0x0000000131b3f510> context, nil block) -> ActionView::AbstractRenderer::RenderedTemplate
This signature was generated using 1 sample from 1 application.
def render(partial, context, block) template = find_template(partial, template_keys(partial)) if !block && (layout = @options[:layout]) layout = find_template(layout.to_s, template_keys(partial)) end render_partial_template(context, @locals, template, layout, block) end
def render_partial_template(view, locals, template, layout, block)
def render_partial_template(view, locals, template, layout, block) ActiveSupport::Notifications.instrument( "render_partial.action_view", identifier: template.identifier, layout: layout && layout.virtual_path, locals: locals ) do |payload| content = template.render(view, locals, add_to_stack: !block) do |*name| view._layout_for(*name, &block) end content = layout.render(view, locals) { content } if layout payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path] build_rendered_template(content, template) end end
def template_keys(_)
def template_keys(_) @locals.keys end