The ultimate goal of your Ruby on Rails application is to render a view.
A view is what the user sees.
It’s the culmination of all the work your app has to do, combining logic, data & view templates to serve the user’s request.
Even returning a JSON response can be considered a view.
That’s why learning everything you can about the rendering system in Rails is pretty important if you don’t want all your work to get wasted.
Rendering in Rails can produce some surprising behavior.
Let’s start with the basics!
By default, you don’t have to tell Rails to render anything & views will still work as long as everything else is set up correctly.
This is part of “Convention over Configuration”.
How does that work?
Well, Rails makes assumptions, which you may be unaware of.
It saves you work.
But if you don’t know what’s going on it may feel like magic.
That’s where you can get into trouble!
In this particular case, the assumption Rails makes is that you want to render a template with the same name as the controller action that is handling the request.
So if you call
BooksController#index… Rails renders
You can get more control over this rendering.
This allows you to render a different view from the default.
class BooksController < ApplicationController def index render :listing end end
.haml if you're using HAML views).
You can use a string instead of a symbol.
Rails will render
Rendering a view associated with another action won't run that action.
In other words, calling
render :index inside
create won't run the
Why is that important?
Because the instance variables for that view won't be set!
You need to set them yourself.
def index @users = User.all end # Missing `@users` here will result in an error or an empty index view # You can use `redirect_to` instead, in that case `index` will run def create render :index end
There's a lot more to rendering than this.
Let's keep going!
Besides rendering a template you have other options.
Rendering a string can be helpful during development to show some kind of error message if you don't have a proper template to handle errors.
Or if you're not ready to write your view yet for a particular controller action.
Here's an example:
if @user render :show else render plain: "User not found." end
Rendering JSON directly can be used to build a simple API, it's not the best approach but it can help you get started.
render json: @user
I haven't used render HTML, but if you have a good use for it let me know!
Rendering goes beyond controllers.
You can also render views within views.
We call that a partial.
Why would you want to do that?
Cleaner code & code reuse.
If you're using the same form on 3 different pages it may be a good idea to extract it into a partial.
Now when you want to make changes you only have to do it in one place.
Here's an example:
<%= render :form %>
For this to work you need to name your view file starting with an underscore, like
_form.erb, but when you call
render you don't need the underscore.
You'll be able to access instance variables from partials...
But what about local variables?
You can do this:
<%= render :form, message: "Apples Are Good" %>
This gives you access to
message as a local variable in your partial.
You're going to learn how you to render multiple things with just one
Partials help you render collections without a loop.
Let's say that you're rendering
You can do this:
<%= render @books %>
This will work if you have a
_book.erb partial & use
book as your variable inside that template.
# app/views/books/_book.erb<%= image_tag(book.cover) %><%= link_to "Read Book", book %>
<%= book.title %><%= book.author %>
If you need the current book number (for your CSS classes) you can use
book_ is the name of your model.
I think collection rendering is one of my favorite Rails features!
When you create a new Rails app it comes with a "layouts" folder under the views folder.
There you'll find the
That's the default layout!
What's a layout?
A layout lets you give your site a consistent look.
Most of the time the default layout is fine.
But what if you want a different layout for a particular page?
You can use the
render :index, layout: 'admin'
You can disable the layout:
render :index, layout: false
And you can set the layout at the controller level.
class AdminsController < ApplicationController layout 'admin' end
One common point of confusion is thinking that rendering (and redirecting) inside a controller action will stop running any code after it.
You can come in contact with this if you call
render multiple times.
def create if yellow_fruit? render :bananas end render :apples end
This will result in an error because
render :apples always runs & you can't render twice in the same action.
Here's the solution:
def create if yellow_fruit? render :bananas else render :apples end end
Another option could be to use the
return keyword after
render, but for clarity, it's best to avoid middle-of-the-method
return statements whenever possible.
You've learned about the all-important topic of rendering in Ruby on Rails.
Rendering allows you to return content to the users of your application & it's one of the final steps inside your controller actions. Understanding rendering helps you write better Rails applications.
Now it's your turn, open your editor & practice your coding skills.
Thanks for reading!