
Posted on • Originally published atrailsdesigner.com
Rails' Partial Features You (didn't) Know
This article was originally published onRails Designer
Partials have been an integral part of Rails. They are conceptually simple to understand, but they pack quite a few smart and lesser known features you might not know about. Let's look at all of them!
Basic rendering
Let's look at the basics of rendering a partial.
<%=renderpartial:"application/navigation"%>
This will render the partialapp/views/application/_navigation.html.erb. The filename starts with an underscore, but is references without one.
You can also omit thepartial
keyword.
<%=render"application/navigation"%>
So far nothing you didn't know already, I assume.
Local Variables
You can pass variables like so.
<%=renderpartial:"user",locals:{user:@user}%>
Again, this short-hand can also be used:
<%=render"user",user:@user%>
Or if you follow conventions from a to z, you could write this:
<%=render@user%>
This assumes a few things:
@user
is present- a partial_user.html.erb inapp/view/users.
Quite a bit cleaner, right? So when does one use the short-hand version and when not? Typically you can use the short-hand version, especially when you are only passing 1 or 2 variables. But you can also pass other arguments; then it's required to use the longer syntax. Like this example:
<%=renderpartial:"user",locals:{admin:@admin},as: :user%>
Explicit local variables
Introduced in Rails 7.2. You can set explicit local variables to clearly tells which variables are required.
<%# locals: (name:) -%><%=name%>
You can also set a default value. So that if the user has no name set, it renders "Stranger".
<%# locals: (name: "Stranger") -%><%=name%>
Local assigns
You can also use “implicit local variables”. Assume the aboveuser_details is used in an admin view.
<div><p><%=name%></p><%local_assigns[:admin?]%><dl><dt> Created at:</dt><dd><%=user.created_at%></dd></dl><%end%></div>
You can render the partial like so:
<%=render"user",user:@user,name:"Cam",admin?:true%>
Or omit theadmin?: true
in non-admin views:
<%=render"user",user:@user,name:"Cam"%>
This is useful, because without thelocal_assigns
, rendering would fail.
Layouts for partials
You can also wrap a partial in a “layout”. This is not to be confused with view layouts stored inapp/views/layouts.
<%=renderpartial:"user",layout:"shared/admin"%>
The admin “layout” is stored atapp/views/shared/_admin.html.erb and could look like this:
<divclass="admin"><%=yield%></div>
Render collection
If you want to render a collection of users, you can write the following, for example inapp/views/users/index.html.erb:
<%=renderpartial:"user",collection:@users%>
Or its shorthand variant:
<%=render@users%>
This automatically looks up the_user.html.erb partial inapp/views/users, assuming@users
is a collection ofUser's.
It doesn't have to a collection of one and the same Resource though, e.g.User. This too works:
<%=render[User.first,Admin.first,Customer.first,User.second]%>
This is assuming you have those resources, and each has their respective partial, e.g. _user.html.erb, _admin.html.erband_customer.html.erb.
Empty State
If the collection, e.g.@users
is empty,render
returnsnil
. So if you want to render an empty state, that is simple.
<%=render(@users)||"No users yet…"%>
Local variables
You can change the the local variable with a collection too.
<%=renderpartial:"user",collection:@users,as: :customer%>
In the_user.html.erb partial, you can now usecustomer.id
(or whatever other attribute is available).
You also pass other variables:
<%=renderpartial:"user",collection:@users,locals:{admin?:true}%>
Counter variables
You can render a counter too:<%%= user_counter %>
. The name, the part before the underscore, is derived from the partial name. So**customer.html.erb* would be*<%%= customer_counter %>
.
Layout for collections
Similarly to resource partials, you can also pass collections partials thelayout option.
<%=renderpartial:@users,layout:"users/wrapper"%>
Then inapp/views/users/_wrapper.html.erb, you could have something like this:
<ulid="users"><%=yield%></ul>
Spacer template
There is one last option for collection which isspacer templates. It will be inserted between each instance. Use it like so:
<%=renderpartial:@users,spacer_template:"user/divider"%>
This will load the partialapp/views/users/_divider.html.erb.
Bonus: Make partials look like components
If you have usedViewComponent, but can't use them in your current project for whatever reason, here's a way you make your partials quack a bit more like ViewComponent.
Create your components inapp/view/components. For example a_card.html.erb.
<sectionclass="card"><h4class="card__header"><%=title%></h4><divclass="card__body"><%=yield%></div></section>
Then in your view use it like this:
<%=renderlayout:"components/card",locals:{title:"User Profile"}do%><p>Just some text for this user</p><%end%>
But you probably want a helper to abstract some of that boilerplate away.
# app/helpers/components_helper.rbmodule ComponentsHelper def component(name, **,&) render layout: "components/#{name}", locals: **,& endend
Now you render it like this:
<%=component"card",title:"User Profile"do%><p>Just some text for this user</p><%end%>
Pair that with theExplicit local variables and you got a pretty solid component-like set up without any dependencies.
And that are all the things you (didn't) know about Rails' partials.
Top comments(1)

- Email
- LocationAmsterdam, The Netherlands
- Joined
Quite surprising this amount of features, isn't it? Which one was new to you?
For further actions, you may consider blocking this person and/orreporting abuse