← Blog
Smart page titles in Ruby on Rails
- Programming
- Ruby on Rails
Having separate titles for each page in a Rails application is a very common requirement and yet RoR does not provide any built in ways to deal with it. I am going to present you with some handy code that can solve this problem without the use of gems.
There are going to be 3 ways to define a page title:
- For the whole controller.
- For a specific action inside a controller.
- Implicitly from a controller name.
Last is gonna be especially useful, you can just drop the following code into your application and have reasonably good titles.
So let’s add code to our parent ApplicationController:
class ApplicationController < ActionController::Base
before_filter :set_page_title
CONTROLLER_TITLES = Hash.new
# for setting page titles for the whole controller
def self.page_title title
CONTROLLER_TITLES[self.name] = title
end
# for setting page titles for a specific actions.
# this overrides @page_title previously set in before_filter
def page_title title
@page_title = title
end
private
def set_page_title
@page_title = CONTROLLER_TITLES[self.class.name] || controller_implicit_title
end
def controller_implicit_title
@@controller_implicit_titles ||= Hash.new
# remove any namespaces and mentions of controller
# so Client::OrdersController becomes "Orders"
@@controller_implicit_titles[self.class.name] ||= self.class.name.gsub(/(.+::)/, '').gsub('Controller', '').underscore.gsub('_', ' ').titleize
end
end
And reference page title in our layout:
<!DOCTYPE html>
<html>
<head>
<title><%= @page_title || 'My Awesome App'%></title>
</head>
<body>
<%= yield %>
</body>
After that setting page titles is extremely easy. You don’t even have to do it if you are naming your controllers properly.
class OrdersController < ApplicationController
page_title 'Orders' # unless specified otherwise all pages are gonna have title 'Orders'
def index # Page title == 'Orders'
@orders = Order.all
end
def cancelled # Page title == 'Cancelled Orders'
page_title 'Cancelled Orders'
@orders = Order.cancelled
end
end
class OrderNotesController < ApplicationController
def index # Page title == 'Order Notes'
@note = OrderNote.all
end
def order # Page title == 'Notes for Order #12345'
page_title "Notes for Order ##{params[:order_id]}"
@note = OrderNote.where(order_id: params[:order_id])
end
end