Smart page titles in Ruby on Rails

Having separate titles for each page in 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 use of gems.

There are going to be 3 ways to define a page title:

  • For tho 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 lets 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 pages 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

Popular posts from this blog

HTTP server in Ruby 3 - Fibers & Ractors

Migration locks for TypeORM

Turbocharge HTTP requests in Ruby