a1pj7w
Last Updated: April 04, 2017
·
2.934K
· tilsammans

Rails page titles with the right amount of magic

I've used almost every page title gem in existence. Not one was perfect. My ideal Rails page title:

  • works with almost no code
  • has sane defaults
  • requires no gem
  • works in Rails 2, 3 and 4 (heck, 5 too!)
  • is completely I18n compatible

And by golly I have found a perfect setup!

Built in

We've all seen this:

content_for?(:title) ? yield(:title) : "Example"

which is great but not flexible. We want I18n. And for 90% of my page titles, they are static, I don't want to have any line in my view.

I am thinking of something like this:

t("#{ controller_path.tr('/', '.') }.#{ action_name }.title")

in my layout which will look up a lazy translation key just like Rails has built in. They start with a dot: t('.title').

This allows me to put almost all my static page titles in the locale file:

# config/en.yml
en:
  products:
    index:
      title: "All products"

But there is always that pesky product show action where you want the product name in the title. Gotta feed the SEO monster after all. Team, I've struggled for years to dig up the cleanest solution. I went through swamps, my quest led me to the depths of Ruby, C and--yes--Java. But I persevered. And today team I present my solution. Stand on my shoulders. Rise!

Step 1

First we will create an old fashioned helper to help keep our view clean.

module ApplicationHelper

  def title
    if content_for?(:title)
      # allows the title to be set in the view by using t(".title")
      content_for :title
    else
      # look up translation key based on controller path, action name and .title
      # this works identical to the built-in lazy lookup
      t("#{ controller_path.tr('/', '.') }.#{ action_name }.title", default: :site_name)
    end
  end

end

Great. Now

Step 2

we put that bad boy in the application layout:

<title><%= title %></title> <!-- see what I did? I made ERB clean! HOLY SHIT! -->
%title= title # haml. still bad ass.
title = title # slim, baby.

Step 3

Put static titles in the locale file. Use the lazy-i18n convention, your key is named title:

en:
  products:
    index:
      title: "All our products"

Step 4

If we want to put something dynamic in the title, use content_for in a view file:

<%= content_for :title, t(".title", name: @product.name) %>

and add the corresponding i18n:

en:
  products:
    show:
      title: "Choose %{name}!"

That's it, sheriff.

2 Responses
Add your response

28227

Great solution!

over 1 year ago ·
28780

im a newbie to rails and i might be wrong here but i find Michael Hartl's dynamic <title> on a view using <%=yield%> and <%provide%> simple and cleaner.

https://www.railstutorial.org/book/static_pages#code-home_view_erb_title

over 1 year ago ·