Rails 3 - Ideal way to set title of pages

Ruby on-Rails-3

Ruby on-Rails-3 Problem Overview


Whats the proper way to set the page title in rails 3. Currently I'm doing the following:

app/views/layouts/application.html:

<head>
  <title><%= render_title %></title>
  <%= csrf_meta_tag %>

app/helpers/application_helper.rb:

def render_title
  return @title if defined?(@title)
  "Generic Page Title"
end

app/controllers/some_controller.rb:

def show
  @title = "some custom page title"
end

Is there another/better way of doing the above?

Ruby on-Rails-3 Solutions


Solution 1 - Ruby on-Rails-3

you could a simple helper:

def title(page_title)
  content_for :title, page_title.to_s
end

use it in your layout:

<title><%= yield(:title) %></title>

then call it from your templates:

<% title "Your custom title" %>

hope this helps ;)

Solution 2 - Ruby on-Rails-3

There's no need to create any extra function/helper. You should have a look to the documentation.

In the application layout

<% if content_for?(:title) %>
  <%= content_for(:title) %>
<% else %>
  <title>Default title</title>
<% end %>

In the specific layout

<% content_for :title do %>
  <title>Custom title</title>
<% end %>

Solution 3 - Ruby on-Rails-3

I found that apeacox's solution didn't work for me (in Rails 3.0.3).

Instead I did...

In application_helper.rb:

def title(page_title, options={})
  content_for(:title, page_title.to_s)
  return content_tag(:h1, page_title, options)
end

In the layout:

<title><%= content_for(:title) %></title>

In the view:

<% title "Page Title Only" %>

OR:

<%= title "Page Title and Heading Too" %>

Note, this also allows us to check for the presence of a title and set a default title in cases where the view hasn't specified one.

In the layout we can do something like:

<title><%= content_for?(:title) ? content_for(:title) : 'This is a default title' %></title>

Solution 4 - Ruby on-Rails-3

This is my preferred way of doing it:

application_helper.rb

module ApplicationHelper
  def title(*parts)
  	content_for(:title) { (parts << t(:site_name)).join(' - ') } unless parts.empty?
  end
end

views/layouts/application.html.erb

<title>
  <%= content_for?(:title) ? yield(:title) : t(:site_name) %>
</title>

config/locales/en.yml

en:
  site_name: "My Website"

This has the nice advantage to always falling back to the site name in your locales, which can be translated on a per-language basis.

Then, on every other page (eg. on the About page) you can simply put:

views/home/about.html.erb

<% title 'About' %>

The resulting title for that page will be:

About - My Website

Simples :)

Solution 5 - Ruby on-Rails-3

@akfalcon - I use a similar strategy, but without the helper.. I just set the default @title in the application controller and then use, <%=@title%> in my layout. If I want to override the title, I set it again in the controller action as you do. No magic involved, but it works just fine. I do the same for the meta description & keywords.

I am actually thinking about moving it to the database so an admin could change the titles,etc without having to update the Rails code. You could create a PageTitle model with content, action, and controller. Then create a helper that finds the PageTitle for the controller/action that you are currently rendering (using controller_name and action_name variables). If no match is found, then return the default.

@apeacox - is there a benefit of setting the title in the template? I would think it would be better to place it in the controller as the title relates directly to the action being called.

Solution 6 - Ruby on-Rails-3

I prefer this:

module ApplicationHelper
  def title(*page_title)
    if Array(page_title).size.zero?
      content_for?(:title) ? content_for(:title) : t(:site_name)
    else
      content_for :title, (Array(page_title) << t(:site_name)).join(' - ')
    end
  end
end

If title is called without arguments, it returns the current value of title or the default which in this example will be "Example".

It title is called with arguments, it sets it to the passed value.

# layouts/application.html.erb
<title><%= title %></title>

# views/index.html.erb
<% title("Home") %>

# config/locales/en.yml
en:
  site_name: "Example"

Solution 7 - Ruby on-Rails-3

You can also check this railscast. I think it will be very useful and give you basic start.

NOTE: In case you want more dynamic pages with pjax

Solution 8 - Ruby on-Rails-3

I have a somewhat more complicated solution. I want to manage all of my titles in my locale files. I also want to include meaningful titles for show and edit pages such that the name of the resource is included in the page title. Finally, I want to include the application name in every page title e.g. Editing user Gustav - MyApp.

To accomplish this I create a helper in application_helper.rb which does most of the heavy lifting. This tries to get a name for the given action from the locale file, a name for the assigned resource if there is one and combines these with the app name.

# Attempt to build the best possible page title.
# If there is an action specific key, use that (e.g. users.index).
# If there is a name for the object, use that (in show and edit views).
# Worst case, just use the app name
def page_title
  app_name = t :app_name
  action = t("titles.#{controller_name}.#{action_name}", default: '')
  action += " #{object_name}" if object_name.present?
  action += " - " if action.present?
  "#{action} #{app_name}"
end

# attempt to get a usable name from the assigned resource
# will only work on pages with singular resources (show, edit etc)
def object_name
  assigns[controller_name.singularize].name rescue nil
end

You will need to add action specific texts in your locale files in the following form:

# en.yml 
titles:
  users:
    index: 'Users'
    edit: 'Editing'

And if you want to use meaningful resource names in your singular views you may need to add a couple of proxy methods, e.g.

# User.rb
def name
  username
end

Solution 9 - Ruby on-Rails-3

I thought it will be good:

<title>
    <% if @title %>
      <%= @title %>
    <% else %>
      Your title
    <% end %>
</title>

And give a value to @title in your controller, or the title will be Your title

Solution 10 - Ruby on-Rails-3

My answer is more simple:

locales/any_archive.yml:

pt-BR:
  delivery_contents:
    title: 'Conteúdos de Entregas'

  groups:
    title: 'Grupos'

And inside of application.html.slim:

title
  = "App Name: #{t("#{controller_name.underscore}.title")}"

Solution 11 - Ruby on-Rails-3

There's a simple way to manipulate layout variables (title, description, etc.):

# app/views/application.html.erb
<title>
  <%= content_for :title || 'App default title' %>
</title>

# app/views/posts/index.html.erb
<%= content_for :title, 'List of posts' %>

And other pages will have App default title value for their titles

Solution 12 - Ruby on-Rails-3

In application layout:

# app/views/layouts/application.html.erb

<title><%= (yield :title) || 'General title' %></title>

then in each view where you want a specific title:

<% content_for :title, 'Specific title' %>

Solution 13 - Ruby on-Rails-3

There are already some good answers, but I'll add my simple approach. Add this to layouts/application.html

- if content_for?(:title)
  -title = "My site | #{content_for(:title)}"
-else
  -title = "My site | #{controller_name.titleize}"

You automagically get a nice names on all your views like "My site | Posts" -- or whatever the controller happens to be.

Of course, you can optionally set a title on a view by adding:

- content_for(:title, 'About')

and get a title like "My site | About".

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionakfalconView Question on Stackoverflow
Solution 1 - Ruby on-Rails-3Andrea PavoniView Answer on Stackoverflow
Solution 2 - Ruby on-Rails-3griableView Answer on Stackoverflow
Solution 3 - Ruby on-Rails-3JitsView Answer on Stackoverflow
Solution 4 - Ruby on-Rails-3DaniG2kView Answer on Stackoverflow
Solution 5 - Ruby on-Rails-3johnmcalileyView Answer on Stackoverflow
Solution 6 - Ruby on-Rails-3Mark MurphyView Answer on Stackoverflow
Solution 7 - Ruby on-Rails-3Dobromir MinchevView Answer on Stackoverflow
Solution 8 - Ruby on-Rails-3ronan_macView Answer on Stackoverflow
Solution 9 - Ruby on-Rails-3RandyView Answer on Stackoverflow
Solution 10 - Ruby on-Rails-3Bruno CasaliView Answer on Stackoverflow
Solution 11 - Ruby on-Rails-3itsnikolayView Answer on Stackoverflow
Solution 12 - Ruby on-Rails-3tomiosView Answer on Stackoverflow
Solution 13 - Ruby on-Rails-3Dennis BestView Answer on Stackoverflow