RubyGuides
Share this post!

The Ultimate Guide to Rails Rendering

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!

The Basics of View Rendering

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 books/index.erb.

Now:

You can get more control over this rendering.

This allows you to render a different view from the default.

Here’s how:

class BooksController < ApplicationController
  def index
    render :listing
  end
end

This renders books/listing.erb (or .haml if you're using HAML views).

You can use a string instead of a symbol.

Like this:

render 'shared/buttons'

Rails will render shared/buttons.erb.

One Thing You Need to Know

Rendering a view associated with another action won't run that action.

In other words, calling render :index inside create won't run the index method.

Why is that important?

Because the instance variables for that view won't be set!

You need to set them yourself.

Example:

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!

Different Kinds of Rendering

Besides rendering a template you have other options.

You can:

  • Render an HTML string
  • Render a plain text string
  • Render JSON

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.

Example:

render json: @user

I haven't used render HTML, but if you have a good use for it let me know!

How to Render Partials

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.

Next:

You're going to learn how you to render multiple things with just one render call!

How to Render Collections

Partials help you render collections without a loop.

Let's say that you're rendering @books.

You can do this:

<%= render @books %>

This will work if you have a _book.erb partial & use book as your variable inside that template.

Example:

# app/views/books/_book.erb

<%= book.title %>

<%= book.author %>
<%= link_to "Read Book", book %>

If you need the current book number (for your CSS classes) you can use book_counter.

Where book_ is the name of your model.

I think collection rendering is one of my favorite Rails features!

Understanding Layouts

When you create a new Rails app it comes with a "layouts" folder under the views folder.

There you'll find the application.html.erb file.

That's the default layout!

What's a layout?

A layout lets you give your site a consistent look.

It's:

  • The menu
  • The footer
  • Loading of CSS & Javascript files...

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 layout option.

Example:

render :index, layout: 'admin'

You can disable the layout:

render :index, layout: false

And you can set the layout at the controller level.

Like this:

class AdminsController < ApplicationController
  layout 'admin'
end

Rendering Doesn't End an Action

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.

Example:

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.

Summary

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!

Leave a Comment:

3 comments
Tokara says 3 weeks ago

Nice post! Simply explained and to the point.

Reply
    Jesus Castello says 3 weeks ago

    Thanks for reading! 🙂

    Reply
Daniel Moros says 3 weeks ago

Like always, good job! clear and clean… One small correction:

To render a partial with local variables you need the full render partial syntax, you have to include the keyword “partial” after “render” to pass the local variables. For example: render partial: “comments/form”, locals: { message: “Hello World”, comment: comment }.

https://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables

Regards!

Reply
Add Your Reply