Rails 3 - Ideal way to set title of pages
Ruby on-Rails-3Ruby 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,
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".