Rails 3-设置页面标题的理想方法


71

在rails 3中设置页面标题的正确方法是什么?目前,我正在执行以下操作:

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

有另一种/更好的方法来执行上述操作吗?


Answers:


130

您可以使用一个简单的助手:

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

在您的布局中使用它:

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

然后从您的模板中调用它:

<% title "Your custom title" %>

希望这可以帮助 ;)


3
非常优雅;)但可能需要更改帮助程序:content_for :title, page_title.to_s
lks128

4
我编辑了答案以反映安德鲁的建议(安德里亚的解决方案无法在Rails 3中使用)
kikito 2012年

问题是这个答案是错误的。除非这里有魔术师。对于使用此辅助方法设置的标题,title必须在<title> <%= yield(:title)%> </ title>之前调用,并且由于后者大部分位于布局中,因此将无法使用。:人们有问题的理解这个答案stackoverflow.com/questions/17770419/...
麦克Szyndel

1
@MichaelSzyndel你的意思不对。传统上,Rails首先呈现模板,然后呈现布局。随着引入流技术,这会有所变化,但是即使启用了流技术,它仍然可以工作,尽管使用new provideovercontent_for会更好。
number1311407 2013年

1
我想这对Rails 4仍然适用,对吗?如果是,请在答案中的某个地方注意这一点,这样人们就不会怀疑他们是否应该继续搜索其Rails版本是否为4+
mizurnix

52

无需创建任何额外的功能/帮助器。您应该看一下文档

在应用程序布局中

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

在具体的布局

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

41

我发现apeacox的解决方案对我不起作用(在Rails 3.0.3中)。

相反,我做了...

application_helper.rb

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

在布局中:

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

在视图中:

<% title "Page Title Only" %>

要么:

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

注意,这还允许我们检查标题是否存在,并在未指定视图的情况下设置默认标题。

在布局中,我们可以执行以下操作:

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

4
content_for?(:title) || 'This is a default title'更短。
mjnissim 2013年

2
我认为您想要的布局是:<title> <%= content_for?(:title)?yield(:title):'这是默认标题'%> </ title>
Jason Heiss 2014年

1
@mjnissim如果为title设置了值,它将返回“ true”。
卡斯珀·格鲁布

3

这是我的首选做法:

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"

这样做的好处是始终回落到您的语言环境中的站点名称,可以按每种语言进行翻译。

然后,在其他页面(例如,关于页面)上,您可以简单地输入:

views / home / about.html.erb

<% title 'About' %>

该页面的标题为:

关于-我的网站

简单:)


2

@akfalcon-我使用类似的策略,但是没有帮助程序。.我只是在应用程序控制器中设置默认@title,然后在布局中使用<%= @ title%>。如果要覆盖标题,请像您一样在控制器操作中再次设置它。不涉及任何魔术,但效果很好。对于元描述和关键字,我也是如此。

我实际上是在考虑将其移至数据库,以便管理员无需更改Rails代码即可更改标题等。您可以创建具有内容,操作和控制器的PageTitle模型。然后创建一个帮助程序,以查找您当前正在呈现的控制器/操作的PageTitle(使用controller_name和action_name变量)。如果找不到匹配项,则返回默认值。

@apeacox-在模板中设置标题有好处吗?我认为将其放置在控制器中会更好,因为标题与被调用的动作直接相关。


6
在控制器内设置标题不是一个好习惯,因为前者与View有关,而后者与业务逻辑有关。例如,拥有一个“博客”控制器,通常根据post.title设置标题,并且没有理由在控制器中创建标题,而是在模板或布局文件中创建它
Andrea Pavoni 2010年

1

我更喜欢这样:

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

如果title在不带参数的情况下调用,则返回title的当前值或默认值(在本示例中为“ Example”)。

title被调用的参数,将其设置到传递的价值。

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

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

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


0

我有一个更复杂的解决方案。我想在区域设置文件中管理所有标题。我还希望包括用于显示和编辑页面的有意义的标题,以使资源名称包含在页面标题中。最后,我想在每个页面标题中包含应用程序名称,例如Editing user Gustav - MyApp

为此,我创建了一个帮助程序,application_helper.rb其中需要执行大部分繁重的工作。这会尝试从语言环境文件中获取给定操作的名称,如果有资源,则为已分配资源命名,然后将其与应用程序名称结合在一起。

# 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

您将需要以以下形式在区域设置文件中添加特定于操作的文本:

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

而且,如果您想在单个视图中使用有意义的资源名称,则可能需要添加几个代理方法,例如

# User.rb
def name
  username
end

0

我认为这会很好:

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

并在控制器中为@title赋值,否则标题将是 Your title


2
简化:<title> <%= @title或'Title'%> </ title>
WhyEnBe 2015年

0

我的答案更简单:

locales / any_archive.yml

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

  groups:
    title: 'Grupos'

application.html.slim内部:

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

0

有一种简单的方法可以处理布局变量(标题,描述等):

# 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' %>

其他页面将具有App default title其标题的价值


0

在应用程序布局中:

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

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

然后在每个需要特定标题的视图中:

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

0

已经有了一些好的答案,但是我将添加简单的方法。将此添加到layouts / application.html

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

您会在所有视图(例如“我的网站|帖子”)上自动获得漂亮的名称-或控制器恰好是。

当然,您可以通过添加以下内容来选择在视图上设置标题:

- content_for(:title, 'About')

并获得“我的网站|关于”之类的标题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.