Rails is a full-stack framework. It ships with all the tools needed to build amazing web apps on both the front and back end.
在 Rails 6 中有两种不同的工具可以用来管理前端的 CSS、JavaScript 以及 images 等资源,分别是 “Sprockets” 和 “Webpacker”,“Sprockets” 除了 Rails 应用外很少使用,但是 “Webpacker” 不仅在 Rails 中,在其他应用框架中也被广泛的使用。
在 Rails 7 中静态资源的管理已经从 “Webpacker” 改为了 “Import Maps”,用来简化基于 JavaScript 的工具和包管理器 Webpack、Yarn 或者 npm 的使用。
Rails 7 实现了一个愿景,即一种真正的全栈 Web 开发方式,可以同时应对前端和后端的挑战。
Rails 7.0: Fulffilling a vision
本文将使用 Ruby 3.0 和 Rails 7.0 环境,创建 Rails 7 应用,并在该应用中引入 Bootstrap 5。
第一种方式:仅引入 Bootstrap
创建 Rails 项目
首先使用 rails new
命令创建 Rails 项目:
如果创建项目的时间过长,可以考虑更换 Ruby 的 Gem 源,使用 RubyChina 的源:
# 删除国外源,使用 RubyChina 的源
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
安装 importmap
项目创建完成后进入项目目录,首先检查config目录下是否包含 “importmap.rb” 文件,如果没有可以通过 rails importmap
命令来安装:
cat config/importmap.rb
# 安装 importmap
rails importmap:install
添加 Bootstrap 5
# 在项目目录下执行 importmap 命令,安装 Bootstrap 5
bin/importmap pin bootstrap
该命令执行后会在 config/importmap.rb
中添加命令行中打印出的内容。
在安装 importmap 是创建的 app/javascript/application.js
文件中导入 ”bootstrap“:
// ...
// 新增内容
import 'bootstrap'
// ...
安装 Bootstrap 5 Ruby Gem
在 Gemfile 中新增如下内容:
# Gemfile
# ...
gem 'bootstrap', '~> 5.2.3'
# ...
保存后执行 bundle install
命令安装依赖。
application.scss 中导入 bootstrap
将 app/assets/stylesheets/application.css
重命名为app/assets/stylesheets/application.scss
# 更改文件后缀为 scss
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
增加内容:
// app/assets/stylesheets/application.scss
// ...
@import "bootstrap";
// ...
测试 Bootstrap
使用 rails g controller
命令创建一个 home_controller 以及 index 函数:
参考 Bootstrap Navabar 的样式修改 app/views/layouts/application.html.erb
页面
<!DOCTYPE html>
<html>
<head>
<title>RailsBootstrap</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf\_meta\_tags %>
<%= csp\_meta\_tag %>
<%= stylesheet\_link\_tag "application", "data-turbo-track": "reload" %>
<%= javascript\_importmap\_tags %>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<div class="container-fluid">
<a class="navbar-brand" href="#">Top navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</header>
<%= yield %>
</body>
</html>
修改 app/views/home/index.html.erb
页面:
<div class="bg-light p-5 rounded">
<h1>Navbar example</h1>
<p class="lead">This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in its original position and moves with the rest of the page.</p>
<a class="btn btn-lg btn-primary" href="/docs/components/navbar/" role="button">View navbar docs »</a>
</div>
通过 rails s
命令启动 Rails 应用,在浏览器中输入 localhost:3000/home/index
查看 index 页面
出现该页面说明引入的 Bootstrap 已经生效。
第二种方式:引入 Bootstrap 和 jQuery
添加 Bootstrap 和 jQuery 的 Ruby Gem
创建一个新的项目 rails-bootstrap-jquery,之后再项目的 Gemfile 中添加如下 Ruby Gems:
gem "sassc-rails"
gem "bootstrap", "~> 5.2.3"
gem "jquery-rails"
执行 bundle install 命令。
接着执行如下命令,修改application.css 后缀,创建 custom.css 以及 my_script.js 文件:
# 修改 application.css 为 application.scss
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
# 创建 custom.scss
touch app/assets/stylesheets/custom.scss
# 创建 my\_script.js
touch app/javascript/my\_script.js
在 application.scss 中添加如下内容:
@import "bootstrap";
@import "custom";
在 config/environments/development.rb
文件中添加如下内容:
config.sass.inline\_source\_maps = true
删除 tmp
文件夹下的缓存:
$ rm -r tmp/cache/assets
在 config/importmap.rb
文件中添加如下内容:
# From "jquery-rails" gem
pin "jquery", to: "jquery3.min.js", preload: true
pin "jquery\_ujs", to: "jquery\_ujs.js", preload: true
# From "bootstrap" gem
pin "bootstrap", to: "bootstrap.min.js", preload: true
pin "@popperjs/core", to: "popper.js", preload: true
# Custom JS
pin "my\_script", to: "my\_script.js", preload: true
在 config/initializers/assets.rb
中添加内容:
Rails.application.config.assets.precompile += %w( jquery3.min.js jquery\_ujs.js bootstrap.min.js popper.js )
在 app/javascript/application.js
中使用 import 关键字导入:
import "jquery";
import "jquery\_ujs";
import "@popperjs/core";
import "bootstrap";
import "my\_script";
在 app/javascript/my\_script.js
中添加如下 JS 代码:
document.addEventListener("turbo:load", () => {
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
const popoverList = [...popoverTriggerList].map((popoverTriggerEl) => new bootstrap.Popover(popoverTriggerEl));
});
在 app/assets/stylesheets/custom.scss
中添加如下样式:
.body-offset {
margin-top: 50px;
}
测试 Bootstrap
创建一个 home_controller.rb
rails g controller home index
修改 app/views/layouts/application.html.erb
Layout 布局:
<!DOCTYPE html>
<html>
<head>
<title>RailsBootstrapJquery</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf\_meta\_tags %>
<%= csp\_meta\_tag %>
<%= stylesheet\_link\_tag "application", "data-turbo-track": "reload" %>
<%= javascript\_importmap\_tags %>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<div class="container-fluid">
<a class="navbar-brand" href="#">Top navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</header>
<%= yield %>
</body>
</html>
修改 app/views/home/index.html.erb
页面:
<div class="container">
<div class="row">
<div class="col-md-8 mt-4">
<button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" data-bs-title="Popover title" data-bs-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>
</div>
</div>
<div class="row mt-4">
<div class="col-md-8">
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Top popover">
Popover on top
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="right" data-bs-content="Right popover">
Popover on right
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Bottom popover">
Popover on bottom
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="left" data-bs-content="Left popover">
Popover on left
</button>
</div>
</div>
</div>
使用 rails s
启动 Rails 项目,查看 http://0.0.0.0:3000/home/index