Skip to content

Ruby on Rails - 布局

在 Rails 中,布局(Layouts)定义了围绕视图(views)的通用结构。它们允许您在应用程序的多个页面上保持一致的页眉(header)、页脚(footer)、导航(navigation)以及整体外观和感觉。布局文件位于 app/views/layouts/ 目录。

默认情况下,Rails 使用一个名为 application.html.erb 的布局文件。当控制器动作(controller action)渲染视图时,Rails 会将该视图的内容包装在此布局中。

让我们为图书馆应用程序创建一个自定义布局。我们将其命名为 library_layout.html.erb 并放置在 app/views/layouts/ 目录中。

将以下 HTML 和 ERB 代码添加到 app/views/layouts/library_layout.html.erb 文件中:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Library Info System</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
</head>
<body id="library-app">
<div id="container">
<header id="main-header">
<h1>Library Information System</h1>
<h3>Powered by Ruby on Rails</h3>
</header>
<nav id="main-nav">
<!-- Navigation links can go here -->
<%= link_to "Home (Books List)", books_path %>
</nav>
<main id="content">
<%# Display flash messages %>
<% flash.each do |type, msg| %>
<div class="alert alert-<%= type %>"><%= msg %></div>
<% end %>
<%= yield %> <%# This is where the content of individual views will be inserted %>
</main>
<aside id="sidebar">
<!-- Sidebar content can go here -->
<h4>Subjects</h4>
<ul id="subjects-sidebar">
<%# You might load @subjects here if available globally or via a helper %>
<%# Subject.all.each do |subject| %>
<%# content_tag :li, link_to(subject.name, subject_path(subject)) %>
<%# end %>
</ul>
</aside>
<footer id="main-footer">
<p>&copy; <%= Time.now.year %> Library Info System</p>
</footer>
</div>
</body>
</html>

此布局中的关键元素:

  • <!DOCTYPE html>:标准的 HTML5 文档类型声明。
  • <meta charset="utf-8"> 和 <meta name="viewport" ...>:必要的元标签。
  • csrf_meta_tags 和 csp_meta_tag:Rails 提供的与安全相关的助手方法。
  • stylesheet_link_tag "application", ...:包含应用程序编译后的 CSS(由 Sprockets 或 Webpacker/Shakapacker 通过 app/assets/stylesheets/application.css 或类似文件管理)。
  • javascript_include_tag "application", ...:包含应用程序编译后的 JavaScript。
  • <%= yield %>:这是最重要的部分。它是您的特定视图(例如 index.html.erb、show.html.erb)的内容将被插入的地方。
  • 闪现消息(Flash messages):一种常见的模式,用于向用户显示信息性消息或错误。
  • 导航(Navigation)、页眉(header)、页脚(footer)、侧边栏(sidebar):常见的结构元素。

要告知您的 BooksController(或任何其他控制器)使用此新布局,您可以在控制器文件的顶部指定它:

app/controllers/books_controller.rb
class BooksController < ApplicationController
layout 'library_layout'
def index
@books = Book.all
# Assuming you want to show all subjects in the sidebar of the layout
# This is just one way; helpers or before_actions are also options for shared data
@all_subjects_for_layout = Subject.order(:name)
end
# ... other actions ...
end

如果您希望应用程序中的所有控制器默认使用此布局,可以将 library_layout.html.erb 重命名为 application.html.erb,或在 ApplicationController 中指定它:

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
layout 'library_layout'
end

现在,当您浏览由 BooksController 处理的页面时,它们将在 library_layout.html.erb 结构中渲染。

应用程序的样式通常在 app/assets/stylesheets/ 中管理。application.css(或 application.scss/application.sass)文件通常充当清单文件(manifest),导入其他样式表。

创建或编辑 app/assets/stylesheets/application.css(或创建一个新文件,如 custom_styles.css,并使用 *= require custom_styles 将其导入到 application.css)。

/* Example styles for app/assets/stylesheets/custom_styles.css */
body#library-app {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: medium;
color: #333;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
#container {
width: 960px;
margin: 20px auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
#main-header h1, #main-header h3 {
text-align: center;
color: #2c3e50;
}
#main-header h1 { margin-bottom: 0; }
#main-header h3 { margin-top: 5px; color: #7f8c8d; }
#content {
padding: 15px;
min-height: 300px; /* Example */
}
/* Add more specific styles for your elements */
ul#books, ul#subjects-sidebar {
list-style-type: none;
padding-left: 0;
}
ul#books li, ul#subjects-sidebar li {
line-height: 1.6;
margin-bottom: 5px;
padding: 5px;
border-bottom: 1px dotted #eee;
}
.alert {
padding: 10px;
margin-bottom: 15px;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-notice { background-color: #dff0d8; border-color: #d6e9c6; color: #3c763d; }
.alert-alert { background-color: #f2dede; border-color: #ebccd1; color: #a94442; }

确保此 CSS 由 Sprockets(或您选择的资产管道工具)处理。如果您创建了 custom_styles.css,请确保 app/assets/stylesheets/application.css 包含了它,例如,如果 application.css 是清单文件,可以使用 *= require custom_styles;如果是 application.scss,可以使用 @import "custom_styles";。

在添加样式后刷新浏览器,您应该会看到应用程序呈现出由您的布局和 CSS 定义的新外观和感觉。

布局提供了一致的外壳。下一章将讨论脚手架(Scaffolding),这是 Rails 的一个特性,可以快速为某个资源生成一套完整的模型(model)、视图(views)、控制器(controller)和路由(routes),这可以作为很好的起点或学习工具。