Rails: 如何更改页面的标题?

在不使用插件的情况下,在 Rails 应用程序中为页面创建自定义标题的最佳方法是什么?

87984 次浏览

没有关于用例或需求的更多细节,我可以想出几个替代方案:

1)在布局页面中切换标题,使用存储在 application_helper.rb中的 helper 方法

<title><%= custom_title %></title>

这种方法将为每个布局页面提供唯一的标题。

2) Railcast 建议使用局部加载 HEAD 标签之间显示的内容

3)使用 javascript/ajax 调用来操作 DOM,如果你需要在加载事件之后更改标题的话。

也许您实际上并不想更改由 title元素标记的内容。也许您确实需要某种类型的面包屑,这样您的用户就总是知道相对于您的站点的导航层次结构他们在哪里。虽然我已经做了很好的如何 Goldberg 插件,我肯定有其他方法实现同样的功能。

最佳实践是使用 content _ for。

首先,添加几个 helper 方法(例如,在 app/helpers/application _ helper. rb 中添加) :

def page_title(separator = " – ")
[content_for(:title), 'My Cool Site'].compact.join(separator)
end


def page_heading(title)
content_for(:title){ title }
content_tag(:h1, title)
end

然后在你的布局视图中,你可以简单地使用:

<title><%= page_title %></title>

以及视野本身:

<%= page_heading "Awesome" %>

这种方法的优点是,可以随意移动标题的 h1标签,并使控制器保持漂亮,不会出现讨厌的@title 变量。

还可以在控制器中的 before _ filter 中设置它。

# foo_controller.rb


class FooController < ApplicationController


before_filter :set_title


private


def set_title
@page_title = "Foo Page"
end


end


# application.html.erb


<h1><%= page_title %></h1>

然后可以在 Set _ title方法中设置条件,为控制器中的不同操作设置不同的标题。能够在控制器中看到所有相关的页面标题非常好。

在你看来,应该这样做:

<% content_for :title, "Title for specific page" %>
<!-- or -->
<h1><%= content_for(:title, "Title for specific page") %></h1>

布局文件中包含以下内容:

<head>
<title><%= yield(:title) %></title>
<!-- Additional header tags here -->
</head>
<body>
<!-- If all pages contain a headline tag, it's preferable to put that in the layout file too -->
<h1><%= yield(:title) %></h1>
</body>

也可以在 helper 方法中封装 content_foryield(:title)语句(正如其他人已经建议的那样)。但是,在这种简单的情况下,我喜欢将必要的代码直接放入特定的视图中,而不使用自定义助手。

我想加上我的简单变体。

在 ApplicationController 中定义此方法:

  def get_title
@action_title_name || case controller_name
when 'djs'
'Djs'
when 'photos'
'Photos'
when 'events'
'Various events'
when 'static'
'Info'
when 'club'
'My club'
when 'news'
'News'
when 'welcome'
'Welcome!'
else
'Other'
end
end

之后,可以从布局的 title 标记中调用 get _ title。通过在操作中定义@action _ title _ name 变量,可以为页面定义更具体的标题。

这里有一个我喜欢使用的简单选项

在你的布局里

<head>
<title><%= @title %></title>
</head>

在页面模板的顶部(第一行)

<% @title="Home" %>

由于解析布局和页面模板的方式,在呈现布局之前会对@title = “ Home”进行计算。

我使用 nifty _ Generator 的“ nifty _ layout”,它提供了一个 title 变量,我可以在页面上调用它,方法是:

<% title "Title of page" %>

我也可以用户 <% title "Title of page", false %>的标题只显示在浏览器的标题,而不是在页面本身。

做到这一点的最佳/干净的方法:

<title><%= @page_title or 'Page Title' %></title>

@ opsb的改进和 @ Fouz更完整的形式:

application.html.erb:

<title><%= @title || "Default Page Title" %></title>

在视图 erb 文件或其控制器中:

<% @title = "Unique Page Title" %>

使用 content _ for 方法和部分

1. 局部名称: _ page _ title.html. erb

<%content_for :page_title do %>
<%=title%>
<%end%>

2. title 标签中 application.html.erb 的用法

   <title><%=yield :page_title %></title>

3. 不包括 application.html.erb 在各自 * . html.erb 中的用法 只要把这个放在任何.html.erb 中并提供页面的标题

    e.g : inside index.html.erb


<%=render '_page_title', title: 'title_of_page'%>

简而言之,我可以这样写下来

<%content_for :page_title do %><%= t :page_title, "Name of Your Page" %> <% end %>

我喜欢 opsb 的方法,但这个方法也行。

<% provide(:title,"ttttttttttttttttttZ") %>
<html>
<head><title><%= yield(:title) %></title></head>
<body></body>
</html>

这个简单的方法设置了默认标题,但是也允许您随时覆盖它。

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

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

要覆盖该默认值,请将其放在任何您喜欢的视图中

<% content_for :title, "some new title" %>

我希望确保总是为当前页面提供翻译。

这是我在 app/views/layouts/application.html.erb中想到的:

    <title>
<%= translate("#{controller_name}.#{action_name}.site_title", raise: true) %>
</title>

这将始终查找当前视图的转换,如果没有找到转换,将引发错误。

如果你想要违约,你可以这样做:

    <title>
<%= translate("#{controller_name}.#{action_name}.site_title",
default: translate(".site_title")) %>
</title>

已经有几个很好的答案,但是这里是我如何最终在 Rails 7中使用几个答案的组合来解决这个问题的。这个解决方案让我想想:

  • 提供完全控制的整个标题
    例如: 「我了不起的定制标题」
  • 只提供一个页面标题,它就会自动附加网站标题
    例如: 「物品-我的应用程式」
  • 不提供任何内容,只显示站点标题
    例如: 「我的应用程式」
  • 将以上所有内容本地化

准备好

本地化

# config/locales/en.yml
en:
layouts:
application:
site_title: "My App"

模板逻辑

# app/views/layouts/application.html.erb
<title>
<%= yield(:title).presence ||
[yield(:page_title).presence, t(".site_title")].compact.join(" - ") %>
</title>

助手的逻辑

注意从 yieldcontent_for的切换

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


# app/helpers/application_helper.rb
module ApplicationHelper
def show_title
content_for(:title).presence ||
[content_for(:page_title).presence, t(".site_title")].compact.join(" - ")
end
end

用法

完全定制的标题

# app/views/static_pages/welcome.html.erb
<% content_for :title, "My awesome custom title" %>


# or localised...
# <% content_for :title, t(".custom_title") %>


# Outputs:
# <title>My awesome custom title</title>

页面标题(自动附加网站)

# app/views/products/index.html.erb
<% content_for :page_title, "Items" %>


# or localised...
# <% content_for :page_title, t("Products.model_name.human") %>


# Outputs:
# <title>Items - My App</title>

默认页面标题

# No "content_for" specified


# Outputs:
# <title>My App</title>

关于逻辑的注释

  • 需要使用 .presence将空字符串(如 yield(:title))转换为 nils
  • 如果 yield(:title).presence为零,则 ||告诉 Ruby 计算表达式的另一边
  • 另一方面,我们从页面标题和站点标题的数组开始
  • .compact删除 nils,所以如果页面标题是空白的,我们不会以“-My App”结束
  • `.如果有多个连字符,join (“-”)连接用连字符分隔的项; 如果只有一个连字符,则返回唯一未修改的项; 如果数组为空,则返回空字符串