<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>flchenhp (chenhuaping)</title>
    <link>https://ruby-china.org/flchenhp</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>用 kamal 部署 rails 至阿里云主机总结</title>
      <description>&lt;h2 id="需求背景"&gt;需求背景&lt;/h2&gt;
&lt;p&gt;rails 开发速度很快，体验很好，但是如果无法部署到服务器上，最后也就是自己在本机玩玩，开发的网页服务不能给别人使用。
我在 deepseek 的帮助下经过一周的摸索终于实现了部署，特记录供自己后期查阅，也供其他人借鉴。真的感谢好时代，有 deepseek 不然想也不敢去想我一个个人业余开发者，身边没一个同语言开发指导老师怎么敢去想自行摸索完成部署功能。&lt;/p&gt;
&lt;h3 id="让deepseek总结kamal一次完整部署的生命周期"&gt;让 deepseek 总结 kamal 一次完整部署的生命周期&lt;/h3&gt;
&lt;p&gt;下面是 Kamal 从初始化到部署完成的完整工作流程，每一步都对应具体的操作：&lt;/p&gt;
&lt;h3 id="阶段 0：准备工作（只需一次）"&gt;阶段 0：准备工作（只需一次）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;初始化配置&lt;/strong&gt;：运行&amp;nbsp;&lt;code&gt;kamal init&lt;/code&gt;，生成&amp;nbsp;&lt;code&gt;config/deploy.yml&lt;/code&gt;&amp;nbsp;配置文件&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;配置服务器列表&lt;/strong&gt;：在&amp;nbsp;&lt;code&gt;deploy.yml&lt;/code&gt;&amp;nbsp;中指定服务器的 IP 地址或域名&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;配置容器注册表&lt;/strong&gt;：设置注册表的用户名和密码（通过环境变量加密存储）&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;设置 SSH 密钥&lt;/strong&gt;：确保本地可以免密登录服务器&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;编写 Dockerfile&lt;/strong&gt;：Rails 7+ 会自动生成，确保镜像构建正确&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="阶段 1：初始部署（kamal setup）"&gt;阶段 1：初始部署（&lt;code&gt;kamal setup&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;这个命令会完成服务器的&lt;strong&gt;首次配置&lt;/strong&gt;：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;SSH 连接并安装 Docker&lt;/strong&gt;：连接到配置文件中的服务器，如果 Docker 未安装，自动通过&amp;nbsp;&lt;code&gt;apt-get&lt;/code&gt;&amp;nbsp;安装&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;登录容器注册表&lt;/strong&gt;：在本地和远程服务器上都登录，以便推送和拉取镜像&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;构建 Docker 镜像&lt;/strong&gt;：使用项目根目录的 Dockerfile 构建镜像&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;推送镜像到注册表&lt;/strong&gt;：将构建好的镜像推送到配置的容器注册表&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;在服务器上拉取镜像&lt;/strong&gt;：通过 SSH 命令让服务器从注册表拉取镜像&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;启动 Kamal Proxy&lt;/strong&gt;：确保代理服务正在运行，并监听 80/443 端口&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;启动应用容器&lt;/strong&gt;：基于拉取的镜像启动新的 Docker 容器&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;健康检查&lt;/strong&gt;：验证应用是否响应&amp;nbsp;&lt;code&gt;GET /up&lt;/code&gt;&amp;nbsp;请求（必须返回 200 OK）&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;清理旧资源&lt;/strong&gt;：删除未使用的镜像和停止的容器，防止磁盘占满&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="阶段 2：后续部署（kamal deploy）"&gt;阶段 2：后续部署（&lt;code&gt;kamal deploy&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;这是日常更新应用的命令，&lt;strong&gt;只执行部署流程，不重复安装 Docker&lt;/strong&gt;：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;构建新镜像&lt;/strong&gt;：基于最新的代码构建新版本镜像&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;推送到注册表&lt;/strong&gt;：新镜像被推送到注册表，标签通常是 Git commit hash&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;SSH 连接服务器并拉取新镜像&lt;/strong&gt;：服务器从注册表拉取新版本镜像&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;启动新容器（旧容器仍在运行）&lt;/strong&gt;：在旧容器旁边启动新容器，确保服务不中断&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;健康检查&lt;/strong&gt;：等待新容器通过健康检查（&lt;code&gt;GET /up&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Kamal Proxy 切换流量&lt;/strong&gt;：代理原子性地将流量从旧容器切换到新容器&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;停止旧容器&lt;/strong&gt;：新容器稳定运行后，停止并删除旧容器&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;清理资源&lt;/strong&gt;：删除旧镜像和未使用的容器，释放磁盘空间&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="我理解kamal的功能（没怎么接触过docker）"&gt;我理解 kamal 的功能（没怎么接触过 docker）&lt;/h3&gt;
&lt;p&gt;我理解 kamal 大致功能是先将本机的开发环境和项目通过 docker 打包成镜像，push 到镜像仓库，然后登陆服务器先下载 docker，然后从镜像仓库 pull 这个镜像再还原运行。
之前尝试过在本机和服务机均安装网络代理工具，这一步实现了，但是直接参考 rails guide 部署还是会存在问题，没搞明白。只能尝试将所有可能会用到科学上网的源替换成国内的源。&lt;/p&gt;
&lt;h2 id="部署记录"&gt;部署记录&lt;/h2&gt;&lt;h3 id="step1：准备hello world项目"&gt;step1：准备 hello world 项目&lt;/h3&gt;
&lt;p&gt;新建 rails 项目&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruby -v
rails -v
rails new rails106
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/2101356e-4fc7-4d84-83c6-3c1c2f067627.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;用编辑器（我用的是 trae）打开项目，做初始化保存&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#iterm
git add .
git commit -m "initial commit"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将 gem 源改成 rubychina 的源&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# gemfile
-source "https://rubygems.org"
+source "https://gems.ruby-china.com"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加 hello world 页面&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#iterm
rails g controller welcome index
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/welcome/index.html.erb
+&amp;lt;h1&amp;gt;hello world&amp;lt;/h1&amp;gt;
-&amp;lt;h1&amp;gt;Welcome#index&amp;lt;/h1&amp;gt;
-&amp;lt;p&amp;gt;Find me in app/views/welcome/index.html.erb&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb
  root "welcome#index"
  get "welcome/index"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动项目，查看 hello word 页面&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iterm
bin/dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/0dc47b93-1671-483c-868c-e4d1ad9baacc.png!large" title="" alt=""&gt;
将代码加入 git 保存&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iterm
git add .
git commit -m "add hello world page"
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step2:选择云主机"&gt;step2:选择云主机&lt;/h3&gt;
&lt;p&gt;阿里云主机可以直接添加 docker，免去安装 docker 的麻烦。直接用 root 账号和设定的自定义密码，这个会用于远程服务器。
&lt;img src="https://l.ruby-china.com/photo/flchenhp/aae8e837-a9bf-4496-a43e-6fefb08ed3a7.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;远程主机验证 docker 安装成功：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 云主机命令行
docker --version
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/8e5a47a9-ec2e-47f4-96d2-3a046b19b798.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="step3:申请阿里云容器镜像服务（ACR）"&gt;step3:申请阿里云容器镜像服务（ACR）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;进入控制台&lt;/strong&gt;：登录后搜索“&lt;strong&gt;容器镜像服务&lt;/strong&gt;”&lt;a href="https://www.e-com-net.com/article/1683693229553299456.htm" rel="nofollow" target="_blank" title=""&gt;&lt;/a&gt;，或直接访问&amp;nbsp;&lt;a href="https://cr.console.aliyun.com/" rel="nofollow" target="_blank" title=""&gt;容器镜像服务控制台&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;按提示创建个人版实例&lt;strong&gt;（下面的信息都很重要，部署的配置文件要用）&lt;/strong&gt;
&lt;img src="https://l.ruby-china.com/photo/flchenhp/3889a199-e266-45ce-a281-878eb3537139.png!large" title="" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;按提升建立命名空间
&lt;img src="https://l.ruby-china.com/photo/flchenhp/236e9c62-b255-4d3b-a6af-f3676517a301.png!large" title="" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;按提示设置密码，获取登录命令
&lt;img src="https://l.ruby-china.com/photo/flchenhp/49a00360-015c-4c96-9667-0375a6c79043.png!large" title="" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;获取个人加速器地址
&lt;img src="https://l.ruby-china.com/photo/flchenhp/3eab9292-3ec3-4822-a38c-3233105c35ee.png!large" title="" alt=""&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="step4:在本机下载docker"&gt;step4:在本机下载 docker&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;访问&amp;nbsp;&lt;a href="https://docs.docker.com/desktop/install/mac-install/" rel="nofollow" target="_blank" title=""&gt;Docker Desktop for Mac 下载页面&lt;/a&gt;选择适宜自己电脑版本下载安装&lt;/li&gt;
&lt;li&gt;点击 Mac 顶部菜单栏的 Docker 图标，选择 Settings。在左侧菜单选择 Docker Engine，将阿里云和一些其他的加速器地址填上
&lt;code&gt;
{
"builder": {
"gc": {
  "defaultKeepStorage": "20GB",
  "enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://5ex1e6il.mirror.aliyuncs.com",
"https://docker.1panel.live",
"https://hub.rat.dev",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.xuanyuan.me",
"https://docker.1ms.run"
]
}
&lt;/code&gt;
&lt;img src="https://l.ruby-china.com/photo/flchenhp/143e0e53-27b7-4d20-9a75-99b21880a364.png!large" title="" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;打开“终端”应用，运行&lt;code&gt;docker --version&lt;/code&gt; 和&lt;code&gt;docker run hello-world&lt;/code&gt; 进行验证 docker 是否正确安装&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="step5:进行部署配置"&gt;step5:进行部署配置&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#rails106/config/deploy.yml
-image: rails106
+image: myrailsapp/rails106 # myrailsapp是阿里云的镜像仓库命名空间

-    - 192.168.0.1
+    - 47.x x.xx.236 # 这是阿里云的IP地址

-  server: localhost:5555
+  # 这里填阿里云的镜像仓库的公网地址
+  server: crpi-xxxxxxxxxxx.cn-zhangjiakou.personal.cr.aliyuncs.com 

-  # username: your-user
+  # 这里填阿里云的账号
+  username: chenxxxxxx21

-  # password:
+   # 这里填阿里云的镜像的固定秘密
+  password: cxxxxxx9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;代码类似
&lt;img src="https://l.ruby-china.com/photo/flchenhp/c3815648-e03b-41ce-a17e-a0b4c7dfe760.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# rails106/Dockerfile
-# syntax=docker/dockerfile:1
+# #syntax=docker/dockerfile:1 # 第一行这里要再加个注释符号注释，不然会报错，不知道为什么

-FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
+# FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
+# 要换成ruby的国内的源，不然会卡住
+FROM docker.m.daocloud.io/library/ruby:$RUBY_VERSION-slim AS base

WORKDIR /rails
+# 设定 apt 源为阿里云镜像，不然会卡住
+RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources &amp;amp;&amp;amp; \
+    sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources
# Install base packages
RUN apt-get update -qq &amp;amp;&amp;amp; \
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;代码类似
&lt;img src="https://l.ruby-china.com/photo/flchenhp/597ab9ec-9d1c-45db-a845-e7e0b95d4d35.png!large" title="" alt=""&gt;
加入 git 仓库&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iterm
git add .
git commit -m "add deploy set"
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step6:打部署命令开始部署"&gt;step6:打部署命令开始部署&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iterm
bin/kamal setup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;部署成功：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/fac0b187-0b66-4db4-832d-5ec150a2f4b8.png!large" title="" alt=""&gt;
浏览器输入 ip 测试
&lt;img src="https://l.ruby-china.com/photo/flchenhp/9800797d-1852-4de5-aff6-7eae3416962d.png!large" title="" alt=""&gt;
大功告成！！！&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Mon, 13 Apr 2026 01:25:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/44550</link>
      <guid>https://ruby-china.org/topics/44550</guid>
    </item>
    <item>
      <title>将 macbook pro 自带的 zsh 界面美化升级</title>
      <description>&lt;p&gt;macbook pro 自带的 zsh 界面略简陋，美化升级一下可以带来更好的开发体验，主要通过安装 oh my zsh 和 iterm2 来实现。
原生界面：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/c8ea2373-879a-460d-92c6-8e92c5ce39e7.png!large" title="" alt=""&gt;
美化后的界面：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/ca2508ba-265f-4b6f-8aba-050280a5995a.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="zsh、oh my zsh和iterm2各是什么？"&gt;zsh、oh my zsh 和 iterm2 各是什么？&lt;/h2&gt;
&lt;p&gt;简单来说，它们的关系可以用一个比喻来理解：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zsh&lt;/strong&gt;：是汽车的&lt;strong&gt;发动机&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Oh My Zsh&lt;/strong&gt;：是汽车的&lt;strong&gt;智能驾驶系统、内饰和装饰件&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;iTerm2&lt;/strong&gt;：是汽车的&lt;strong&gt;车身、座椅、仪表盘和控制台&lt;/strong&gt;。
下面我来详细解释每一部分的作用和它们如何协同工作。
* * *
### 1. Zsh (Z Shell) -&amp;nbsp;&lt;strong&gt;“发动机”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它是什么&lt;/strong&gt;：Zsh 是一个&amp;nbsp;&lt;strong&gt;Unix Shell&lt;/strong&gt;，与你可能听说过的 Bash、Ksh、Tcsh 是同一类东西。它是一个&lt;strong&gt;命令行解释器&lt;/strong&gt;，是你和操作系统内核之间进行交互的桥梁。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它的角色&lt;/strong&gt;：它是核心，是真正&lt;strong&gt;执行你的命令&lt;/strong&gt;（如&amp;nbsp;&lt;code&gt;ls&lt;/code&gt;,&amp;nbsp;&lt;code&gt;cd&lt;/code&gt;,&amp;nbsp;&lt;code&gt;git commit&lt;/code&gt;&amp;nbsp;等）的东西。没有它，你的终端窗口就是一个空壳。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Mac 现状&lt;/strong&gt;：从 macOS Catalina (10.15) 开始，Zsh 已经取代 Bash，成为所有新用户账户的&lt;strong&gt;默认 Shell&lt;/strong&gt;。所以你的 MacBook Pro 原生就在使用 Zsh。
### 2. Oh My Zsh -&amp;nbsp;&lt;strong&gt;“智能系统和装饰”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它是什么&lt;/strong&gt;：Oh My Zsh 是一个用于&lt;strong&gt;管理 Zsh 配置&lt;/strong&gt;的&lt;strong&gt;开源框架&lt;/strong&gt;。它本身不是一个独立的 Shell。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它的角色&lt;/strong&gt;：原生的 Zsh 功能强大但配置起来非常复杂，就像一台没有任何内饰和电子系统的裸车发动机。Oh My Zsh 的作用是：

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;简化配置&lt;/strong&gt;：它提供了一个结构化的、易于编辑的配置文件（&lt;code&gt;~/.zshrc&lt;/code&gt;），让你通过简单的修改就能启用强大功能。&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;提供主题&lt;/strong&gt;：它收集了&lt;strong&gt;数百个主题&lt;/strong&gt;（主要是修改命令提示符&amp;nbsp;&lt;code&gt;prompt&lt;/code&gt;&amp;nbsp;的外观），让你一键更换界面风格（如你之前问的 Agnoster 主题）。&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;管理插件&lt;/strong&gt;：它提供了海量的&lt;strong&gt;插件生态系统&lt;/strong&gt;，可以轻松安装和管理插件，为你增加命令补全、语法高亮、Git 状态显示等功能。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;总结&lt;/strong&gt;：Oh My Zsh&amp;nbsp;&lt;strong&gt;不替代 Zsh&lt;/strong&gt;，而是&lt;strong&gt;运行在 Zsh 之上&lt;/strong&gt;，让它变得更强大、更美观、更易用。你没有 Oh My Zsh 也能用 Zsh，但会麻烦很多。
### 3. iTerm2 -&amp;nbsp;&lt;strong&gt;“车身和座舱”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它是什么&lt;/strong&gt;：iTerm2 是一个&lt;strong&gt;终端模拟器&lt;/strong&gt;（Terminal Emulator），是 macOS 自带“终端”（&lt;a href="https://terminal.app/" rel="nofollow" target="_blank" title=""&gt;Terminal.app&lt;/a&gt;）的一个&lt;strong&gt;功能强大的替代品&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;它的角色&lt;/strong&gt;：它是一个&lt;strong&gt;应用程序&lt;/strong&gt;，是显示命令行界面（CLI）的&lt;strong&gt;那个窗口&lt;/strong&gt;。它的职责是：

&lt;ul&gt;
&lt;li&gt;  呈现文本界面&lt;/li&gt;
&lt;li&gt;  处理窗口分割、标签页&lt;/li&gt;
&lt;li&gt;  管理配色方案、字体、光标样式&lt;/li&gt;
&lt;li&gt;  提供搜索、回放、自动完成等增强功能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;关键区别&lt;/strong&gt;：iTerm2&amp;nbsp;&lt;strong&gt;不关心&lt;/strong&gt;你里面运行的是 Zsh、Bash 还是 Fish。你可以在 iTerm2 的设置里指定使用哪个 Shell（比如&amp;nbsp;&lt;code&gt;/bin/zsh&lt;/code&gt;&amp;nbsp;或&amp;nbsp;&lt;code&gt;/bin/bash&lt;/code&gt;）。它只是为 Shell 提供一个更好的“运行环境”和“显示容器”。
* * *
### 三者如何协同工作？
&lt;strong&gt;一个典型的、美化了的工作流程是这样的：&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; 你打开&amp;nbsp;&lt;strong&gt;iTerm2&lt;/strong&gt;&amp;nbsp;应用程序（它代替了难用的原生 Terminal）。&lt;/li&gt;
&lt;li&gt; iTerm2 启动，并根据它的设置，去调用系统的&amp;nbsp;&lt;strong&gt;Zsh&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt; Zsh 启动时，会加载&amp;nbsp;&lt;strong&gt;Oh My Zsh&lt;/strong&gt;&amp;nbsp;的配置框架。&lt;/li&gt;
&lt;li&gt; Oh My Zsh 根据你的&amp;nbsp;&lt;code&gt;~/.zshrc&lt;/code&gt;&amp;nbsp;文件，应用你选择的&lt;strong&gt;主题&lt;/strong&gt;（控制文字、颜色、图标显示）和&lt;strong&gt;插件&lt;/strong&gt;（增加功能）。&lt;/li&gt;
&lt;li&gt; 最终，你看到了一个功能强大、色彩绚丽、提示信息丰富的命令行界面，并在其中高效地工作。
## 具体美化步骤
### step1:用 iTerm2 更换终端模拟器
iTerm2 是一款完全免费的，专为 Mac OS 用户打造的命令行应用，支持分窗、搜索、自动补全、自定义快捷键等强大功能，是替代 macOS 自带 Terminal 的优秀选择。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;安装方法&lt;/strong&gt;：访问&lt;a href="https://iterm2.com/" rel="nofollow" target="_blank" title=""&gt;iTerm2 官网&lt;/a&gt;，下载并拖拽到应用程序文件夹即可。
得到成功如下：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/90fa0ce2-6444-4e57-a26d-3f26b41b3dcd.png!large" title="" alt=""&gt;
打开 item 将主题颜色修改为程序员喜欢的暗黑配色：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/8d73fe59-7798-40e9-a523-d6c9f0fa3b9a.png!large" title="" alt=""&gt;
### step2:安装 oh my zsh
Oh My Zsh 是一个开源的、社区驱动的框架，用于管理 Zsh 配置，它提供了大量的主题和插件，让 Zsh 配置变得简单有趣。
安装指令：&lt;code&gt;sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)"&lt;/code&gt;
得到的成果：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/87d9e652-85b7-4caa-a105-2d432412b04c.png!large" title="" alt=""&gt;
### step3:选择 oh my zsh 主题
oh my zsh 有许多主题，详细可查看&lt;a href="https://github.com/ohmyzsh/wiki/blob/main/Themes.md" rel="nofollow" target="_blank" title=""&gt;oh my zsh 主题列表&lt;/a&gt;。
其中 Agnoster 主题：一款非常流行的主题，显示信息丰富（如 git 状态、上一命令返回值等），是程序员喜欢的一款主题，我也选择这个。
设置步骤：
修改配置文件：&lt;code&gt;nano ~/.zshrc&lt;/code&gt;
注释掉这一行：#ZSH_THEME="robbyrussell"，
添加这行：ZSH_THEME="agnoster"
保存配置退出到命令行
&lt;strong&gt;注意&lt;/strong&gt;：许多漂亮的主题使用了特殊图标，需要安装 Powerline 字体才能正确显示。
安装步骤：依次执行
&lt;code&gt;git clone https://github.com/powerline/fonts.git --depth=1&lt;/code&gt;
&lt;code&gt;cd fonts&lt;/code&gt;
&lt;code&gt;./install.sh&lt;/code&gt;
&lt;code&gt;cd ..&lt;/code&gt;
&lt;code&gt;rm -rf fonts&lt;/code&gt;
选择刚安装的字体： 
&lt;img src="https://l.ruby-china.com/photo/flchenhp/41d79e86-3b52-4709-8329-b77fc15ad5fb.png!large" title="" alt=""&gt;
让修改的配置生效：&lt;code&gt;source ~/.zshrc&lt;/code&gt;，
得到效果图：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/9c92509f-e6ad-4cbe-be0b-0f4d6ab75e39.png!large" title="" alt=""&gt;
### step4:安装 oh my zsh 插件
oh my zsh 的插件列表：&lt;a href="https://github.com/ohmyzsh/wiki/blob/main/Plugins.md" rel="nofollow" target="_blank" title=""&gt;网址链接&lt;/a&gt;，其中 zsh-autosuggestions、zsh-syntax-highlighting 是两个非常推荐的插件。
sh-autosuggestions：根据历史命令自动建议补全，用方向键→或 Ctrl+F 接受建议，效率神器。
下载指令：
&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions&lt;/code&gt;
zsh-syntax-highlighting：为命令提供语法高亮，书写错误时会显示红色，正确则为绿色。
下载指令：
&lt;code&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;将两个插件添加配置文件：
&lt;code&gt;nano ~/.zshrc&lt;/code&gt;
找到插件配置行，原始为：plugins=(git)
修改成：plugins=( git zsh-autosuggestions zsh-syntax-highlighting )
&lt;strong&gt;注意&lt;/strong&gt;：zsh-syntax-highlighting 必须放在最后。&lt;/li&gt;
&lt;li&gt;保存配置后退出到命令行&lt;/li&gt;
&lt;li&gt;使刚修改的配置生效：&lt;code&gt;source ~/.zshrc&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;得到的效果如下图：
&lt;img src="https://l.ruby-china.com/photo/flchenhp/5eb507ae-1db7-49d8-93b5-bcd38e5b2b3a.png!large" title="" alt=""&gt;
### iterm2 常用的命令
&lt;img src="https://l.ruby-china.com/photo/flchenhp/6a7d17b4-2424-4f52-a90b-a40454fe9f7e.png!large" title="" alt=""&gt;
## 搞定
完成任务，给自己点个👍，嘎嘎～&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>flchenhp</author>
      <pubDate>Thu, 04 Sep 2025 17:03:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/44287</link>
      <guid>https://ruby-china.org/topics/44287</guid>
    </item>
    <item>
      <title>在 rails8 项目中引入 bootstrap5</title>
      <description>&lt;h2 id="为什么我选择bootstrap5而不是tailwildcss"&gt;为什么我选择 bootstrap5 而不是 tailwildcss&lt;/h2&gt;
&lt;p&gt;原因是我前端菜鸡，从来没有好好认真写过 css，虽然 tailwildcss 给了原子粒度的工具类名，让你很容易能定制自己的轮子，但是我根本不知道一个能看的过去的轮子怎么搭建，还是 bootstrap 这种直接给出的还比较好看的组件适合我，我可以像搭积木一下搭出一个能比较好看的网页。&lt;/p&gt;
&lt;h2 id="在rails8项目中引入bootstrap5"&gt;在 rails8 项目中引入 bootstrap5&lt;/h2&gt;&lt;h3 id="step1.新建rails8项目"&gt;step1.新建 rails8 项目&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rails new rails101&lt;/code&gt;
&lt;code&gt;cd rails101&lt;/code&gt;
用 rubymine 打开项目：
&lt;code&gt;rubymine .&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="step2.引入bootstrap css和icon"&gt;step2.引入 bootstrap css 和 icon&lt;/h3&gt;
&lt;p&gt;将以下链接添加到 app/views/layouts/application.html.erb 的 &lt;/p&gt; 中，由于我电脑连接 jspm.io 有问题，切换其他 CDN 源为 jsDelivr 或 unpkg 的链接：
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- 引入 Bootstrap CSS 和 Bootstrap icon --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step3.引入bootstrap的js"&gt;step3.引入 bootstrap 的 js&lt;/h3&gt;
&lt;p&gt;在 config/importmap.rb 中添加 bootstrap 的 js 文件的 url&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 将原来的 jspm.io 链接替换为 jsDelivr 或 unpkg 的链接&lt;/span&gt;
&lt;span class="n"&gt;pin&lt;/span&gt; &lt;span class="s2"&gt;"bootstrap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.esm.min.js"&lt;/span&gt;
&lt;span class="n"&gt;pin&lt;/span&gt; &lt;span class="s2"&gt;"@popperjs/core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/esm/popper.min.js"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="测试引入bootstrap的效果"&gt;测试引入 bootstrap 的效果&lt;/h2&gt;&lt;h3 id="step1.生成测试页面"&gt;step1.生成测试页面&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rails g controller home index&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="step2.在config/routes.rb中修改成root路径指向测试页面路径"&gt;step2.在 config/routes.rb 中修改成 root 路径指向测试页面路径&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="s2"&gt;"home#index"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step3.添加bootstrap5的测试代码"&gt;step3.添加 bootstrap5 的测试代码&lt;/h3&gt;
&lt;p&gt;在测试页面 app/views/home/index.html.erb 填入&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-danger"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bi bi-wifi"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;good&lt;span class="nt"&gt;&amp;lt;/i&amp;gt;&lt;/span&gt;Home#index&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Find me in app/views/home/index.html.erb&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container mt-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello, Bootstrap!&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-success"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;data-bs-target=&lt;/span&gt;&lt;span class="s"&gt;"#exampleModal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Launch Demo Modal
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal fade"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"exampleModal"&lt;/span&gt; &lt;span class="na"&gt;tabindex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"exampleModalLabel"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-dialog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"exampleModalLabel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Bootstrap Modal&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-close"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Close"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
            Wow! A modal is working without any build tool!
          &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-secondary"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Close&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step4.浏览器查看效果"&gt;step4.浏览器查看效果&lt;/h3&gt;
&lt;p&gt;启动项目
&lt;code&gt;bin/dev&lt;/code&gt;
在浏览器访问&lt;a href="http://127.0.0.1:3000/" rel="nofollow" target="_blank"&gt;http://127.0.0.1:3000/&lt;/a&gt;
得到效果图如下，bootstrap 的 css、js、icon 功能均生效
&lt;img src="https://l.ruby-china.com/photo/flchenhp/4512c733-54c1-41e4-bee9-87ec65ca78e6.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="用bootstrap为网站添加常用一些partial模块"&gt;用 bootstrap 为网站添加常用一些 partial 模块&lt;/h2&gt;&lt;h3 id="Step 1. 新增 app/views/common 资料夹"&gt;Step 1. 新增 app/views/common 资料夹&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mkdir app/views/common&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="Step 2. 新增 navbar"&gt;Step 2. 新增 navbar&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;touch app/views/common/_navbar.html.erb&lt;/code&gt;
填入&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar navbar-expand-md bg-dark navbar-dark"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Brand --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-brand"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://img1.baidu.com/it/u=2544257883,100398830&amp;amp;fm=253&amp;amp;fmt=auto&amp;amp;app=138&amp;amp;f=JPEG?w=500&amp;amp;h=500"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:40px; margin-left: 15px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Toggler/collapsibe Button --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-toggler"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"collapse"&lt;/span&gt; &lt;span class="na"&gt;data-bs-target=&lt;/span&gt;&lt;span class="s"&gt;"#collapsibleNavbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-toggler-icon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Navbar links --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"collapse navbar-collapse"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"collapsibleNavbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-nav"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Dropdown --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link dropdown-toggle"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"navbardrop"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Dropdown link
        &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 1&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 2&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 3&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control me-2"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-nav ms-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;登录&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;注册&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;联系我们&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Dropdown --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link dropdown-toggle"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"navbardrop"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Dropdown link
        &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 1&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 2&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link 3&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Step 3. 新增 footer
&lt;code&gt;touch app/views/common/_footer.html.erb&lt;/code&gt;
填入&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;footer&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fixed-bottom bg-light p-3 text-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Copyright ©2025 rails101
    &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
    Design by chenhuaping
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Step 4. 新增flashes"&gt;Step 4. 新增 flashes&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;touch app/views/common/_flashes.html.erb&lt;/code&gt;
填入&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="n"&gt;user_facing_flashes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;flash_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt; alert-dismissible"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-close"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;增加 flash 的辅助模块
&lt;code&gt;touch app/helpers/flashes_helper.rb&lt;/code&gt;
填入&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FlashesHelper&lt;/span&gt;
  &lt;span class="no"&gt;FLASH_CLASSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;danger: &lt;/span&gt;&lt;span class="s2"&gt;"danger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;success: &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;warning: &lt;/span&gt;&lt;span class="s2"&gt;"warning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;info: &lt;/span&gt;&lt;span class="s2"&gt;"info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;primary: &lt;/span&gt;&lt;span class="s2"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flash_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;FLASH_CLASSES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_facing_flashes&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt; &lt;span class="s2"&gt;"danger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"warning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"primary"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Step 5. 将新增几个partial加载显示"&gt;Step 5. 将新增几个 partial 加载显示&lt;/h3&gt;
&lt;p&gt;在 app/views/layouts/application.html.erb，将&lt;code&gt;&amp;lt;%= yield %&amp;gt;&lt;/code&gt;换成以下代码：&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container-fluid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"common/navbar"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"common/flashes"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"common/footer"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Step 6. 触发flash功能"&gt;Step 6. 触发 flash 功能&lt;/h3&gt;
&lt;p&gt;在 app/controllers/home_controller.rb 中 index 方法中添加触发代码&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:primary&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"测试flash功能！"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="step7.浏览器中查看效果"&gt;step7.浏览器中查看效果&lt;/h3&gt;
&lt;p&gt;刷新网址&lt;a href="http://127.0.0.1:3000/navbar%E3%80%81footer%E3%80%81flash" rel="nofollow" target="_blank"&gt;http://127.0.0.1:3000/navbar, footer, flash&lt;/a&gt;，均正常显示
&lt;img src="https://l.ruby-china.com/photo/flchenhp/6b166716-62fa-47fb-9c4a-791aee722a4e.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="大功告成"&gt;大功告成&lt;/h2&gt;
&lt;p&gt;给自己点个👍，嘎嘎&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Tue, 02 Sep 2025 13:19:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/44286</link>
      <guid>https://ruby-china.org/topics/44286</guid>
    </item>
    <item>
      <title>macbook pro 安装 rails 开发环境记录</title>
      <description>&lt;p&gt;之前的 macbook pro18 年买的，配置太低 8g 内存 100g 硬盘，经一次换屏幕多次换电池，现在已难以使用，出现硬盘空间不足，在开发高负荷运转时发烫严重、风扇很响问题。我由于不是程序员，业余爱好而已，身边也没有可以指导的老师，rails 代码水平基本停留在 CRUD 水平，本来对 code 已经停了几年的我完全没兴趣的再去淘个 mac 再来练习 code，在上个月偶然尝试用 deepseek 来指导我写个 ruby 脚本解决我工作中遇到的建立 ip 台账的工作，发现竟然成功完成了我的任务，这是我之前不敢想的，因为完全靠我自己，我对这个脚本代码要如何编写毫无头绪，至此打开了让 deepseek 指导我写代码的大门，我尝试让 deepseek 教我实现 devise 的登录触发邮件确认功能，尝试让 deepseek 教我写关注功能（当前琢磨了 2 个月才实现这个功能，deepseek 几十秒就出来了），让我又有了兴趣再继续来玩玩 code，所以在抖音商城淘了个二手的 21 年款 m1 芯片、32g 内存、500g 硬盘的 mac，再次出发来练习练习 code。&lt;/p&gt;

&lt;p&gt;在我的过去的认知，编程领域要出发去探索 ruby on rails 的世界，开发环境安装就是一个很大的拦路虎，小白基本上是很难完全靠自己装载好 rails 的开发环境，特记录我这次在新二手 mac 安装 rails 开发环境的过程，供其他人参考。&lt;/p&gt;

&lt;p&gt;我在安装过程遇到过一些问题，直接把报错黏贴给 deepseek，它会告诉你如何解决，deepseek 真是个不厌其烦的称心老师。&lt;/p&gt;
&lt;h2 id="安装rails开发环境"&gt;安装 rails 开发环境&lt;/h2&gt;&lt;h3 id="1、安装 Xcode"&gt;1、安装 Xcode&lt;/h3&gt;
&lt;p&gt;Mac 上建立程序开发环境的辅助应用程序。&lt;/p&gt;

&lt;p&gt;安装步骤：&lt;/p&gt;

&lt;p&gt;在苹果的 app store 找到后安装、启动执行，首次执行，Xcode 会要求同意“使用者协议”，选择 Agree&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/72c2aba7-e576-4c33-b471-1cca298aab3c.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;安装成功：&lt;/p&gt;

&lt;p&gt;xcode 图形软件可正常启动&lt;/p&gt;
&lt;h3 id="2、安装Command Line Tools"&gt;2、安装 Command Line Tools&lt;/h3&gt;
&lt;p&gt;Command Line Tools 是一种可以编译程序的软件。
但我们不会直接使用它，你可以把它想成是电脑执行编程需要的软体工具跟套件之一就可以了。&lt;/p&gt;

&lt;p&gt;安装步骤&lt;/p&gt;

&lt;p&gt;到 Mac 的 Spotlight&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/6d91c1d4-6926-43ed-be89-f64fde250054.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;搜寻 Terminal&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/206fbc11-0757-4045-9264-d61b6404224f.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;打开你的“Terminal” （终端机）程式。（&lt;em&gt;注意：未来我们都会透过这个程式来输入程序指令&lt;/em&gt;）&lt;/p&gt;

&lt;p&gt;在终端机里输入安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xcode-select --install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;安装成功指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xcode-select -p&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出：/Applications/Xcode.app/Contents/Developer&lt;/p&gt;
&lt;h3 id="3、安装Homebrew"&gt;3、安装 Homebrew&lt;/h3&gt;
&lt;p&gt;Homebrew 是开发者社群专为 MacOSX 打造的第三方套件管理程式，比如说安装 Ruby 需要一些编译工具或函式库，这些工具或函式库，可以从 Homebrew 取得。&lt;/p&gt;

&lt;p&gt;从官网安装：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;使用官网因为网络问题可能会卡，建议使用清华大学镜像安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/bin/bash -c "$(curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/mirror-scripts/install.sh)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;使配置立即生效指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;确认安装成功：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出版本信息：Homebrew 4.6.7&lt;/p&gt;
&lt;h3 id="4、安装ImageMagick和vips"&gt;4、安装 ImageMagick 和 vips&lt;/h3&gt;
&lt;p&gt;ImageMagick 和 vips 是专门处理图片的函式库。未来我们在 Ruby 中常常需要使用 ImageMagick 和 vips 相关的功能，所以通常在初始环境时，我们也会一并先安装。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install imagemagick vips&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;确认是否安装成功？&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vips --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出版本信息：vips-8.17.1&lt;/p&gt;
&lt;h3 id="5、安装PostgresSQL"&gt;5、安装 PostgresSQL&lt;/h3&gt;
&lt;p&gt;PostgresSQL 是一套强大的资料库。许多网站开发预设使用 PostgresSQL 作为底层资料库。在初始环境时，我们也会一并先安装。&lt;/p&gt;

&lt;p&gt;安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install postgresql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;设定开启：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew services start postgresql@14&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;确认安装成功：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;psql --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出版本号：psql (PostgreSQL) 14.19 (Homebrew)&lt;/p&gt;
&lt;h3 id="6、安装RVM"&gt;6、安装 RVM&lt;/h3&gt;
&lt;p&gt;在 Mac 开发 Ruby on Rails 程式时，因为 Ruby 版本更新很快，常常会遇到一些版本与权限上的问题。所以当在开发时，我们通常不会使用系统内建的 Ruby。而是会改采用一套 Ruby Version Manager 去管理 Ruby 的安装与升级。透过 Ruby Version Manager ( RVM) 去安装 Ruby。&lt;/p&gt;

&lt;p&gt;安装 GPG 密钥 (用于验证安装脚本正确性）：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\curl -sSL https://get.rvm.io | bash -s stable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;使 rvm 立即生效：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[[ -s "$HOME/.rvm/scripts/rvm" ]] &amp;amp;&amp;amp; source "$HOME/.rvm/scripts/rvm"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;确认安装成功&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rvm --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出 rvm 版本：rvm 1.29.12 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [&lt;a href="https://rvm.io" rel="nofollow" target="_blank"&gt;https://rvm.io&lt;/a&gt;]&lt;/p&gt;
&lt;h3 id="7、安装ruby"&gt;7、安装 ruby&lt;/h3&gt;
&lt;p&gt;将 gem 源换成国内的速度会快一点：&lt;/p&gt;

&lt;p&gt;gem sources --add &lt;a href="https://gems.ruby-china.com/" rel="nofollow" target="_blank"&gt;https://gems.ruby-china.com/&lt;/a&gt; --remove &lt;a href="https://rubygems.org/" rel="nofollow" target="_blank"&gt;https://rubygems.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ruby 安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rvm install 3.4.5 --with-openssl-dir="$(brew --prefix openssl@3)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;注：我安装时如果不带后面参数会报错，正常应该不用带参数&lt;/p&gt;

&lt;p&gt;ruby 是否安装成功：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rvm list&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输输出已安装成功的版本 ruby：&lt;/p&gt;

&lt;p&gt;ruby-3.4.5 [ arm64 ]&lt;/p&gt;

&lt;p&gt;设定默认使用的 ruby 版本：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rvm alias create default ruby-3.4.5&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;查看当前使用 ruby 版本：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出当前使用 ruby 版本&lt;/p&gt;
&lt;h3 id="8、安装rails"&gt;8、安装 rails&lt;/h3&gt;
&lt;p&gt;rails 是我们开发网站要使用网站框架&lt;/p&gt;

&lt;p&gt;安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gem install rails -v 8.0.2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;确认安装成功：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rails -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出 rails 版本：Rails 8.0.2&lt;/p&gt;
&lt;h3 id="9、安装node和包管理工具yarn"&gt;9、安装 node 和包管理工具 yarn&lt;/h3&gt;
&lt;p&gt;安装指令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install node&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install yarn&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;安装是否成功：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出 node 版本信息：v24.7.0&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会输出 yarn 的版本信息：1.22.22&lt;/p&gt;
&lt;h3 id="10、安装rubymine （非必选，建议此编辑器，其他还有atom等免费方案）"&gt;10、安装 rubymine（非必选，建议此编辑器，其他还有 atom 等免费方案）&lt;/h3&gt;
&lt;p&gt;官网下载安装，淘宝买个激活账号，大概十 - 几十块&lt;/p&gt;
&lt;h2 id="测试rails开发环境是否成功"&gt;测试 rails 开发环境是否成功&lt;/h2&gt;&lt;h3 id="新建rails项目指令："&gt;新建 rails 项目指令：&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rails new rails101&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="设置命令行可启动rubymine打开项目编辑"&gt;设置命令行可启动 rubymine 打开项目编辑&lt;/h3&gt;
&lt;p&gt;用 rubymine 打开这个项目&lt;/p&gt;

&lt;p&gt;然后开始配置后期可通过命令行启动 rubymine 步骤：&lt;/p&gt;

&lt;p&gt;macOS: 点击顶部菜单栏 Tools -&amp;gt; Create Command-line Launcher...。&lt;/p&gt;

&lt;p&gt;它会弹出一个对话框，显示默认的命令和路径（通常是 /usr/local/bin/mine）。&lt;/p&gt;

&lt;p&gt;直接点击 OK 或 Create 即可。&lt;/p&gt;

&lt;p&gt;修改配置启用命令行启动 rubymine 设置：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nano ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;在文件的末尾添加下面这行代码。这行代码的作用是将 RubyMine 的路径追加到现有的 $PATH 变量中。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export PATH="/Applications/RubyMine.app/Contents/MacOS:$PATH"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;在 nano 编辑器中，按 Ctrl + O（写入）、按 回车 确认文件名、按 Ctrl + X（退出）。&lt;/p&gt;

&lt;p&gt;让配置立即生效：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;测试：关闭 rubymine，&lt;code&gt;cd rails01&lt;/code&gt;，&lt;code&gt;rubymine .&lt;/code&gt;,正常 rubymine 就会打开这个项目。&lt;/p&gt;
&lt;h3 id="测试"&gt;测试&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;bin/dev&lt;/code&gt;启动项目，&lt;a href="http://127.0.0.1:3000/" rel="nofollow" target="_blank"&gt;http://127.0.0.1:3000/&lt;/a&gt;可打开出现如下图，说明开发环境配置成功&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/51ea7ebe-4ff9-4a74-bde9-3936cb79402c.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="大功告成"&gt;大功告成&lt;/h2&gt;
&lt;p&gt;大约花了我 1 天多的时间～&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Sun, 31 Aug 2025 23:01:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/44263</link>
      <guid>https://ruby-china.org/topics/44263</guid>
    </item>
    <item>
      <title>收集的可用的 ruby gem 源</title>
      <description>&lt;p&gt;1、官方的：&lt;a href="https://rubygems.org" rel="nofollow" target="_blank"&gt;https://rubygems.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2、rubychina 的：&lt;a href="https://gems.ruby-china.com" rel="nofollow" target="_blank"&gt;https://gems.ruby-china.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3、清华的：&lt;a href="http://mirrors.tuna.tsinghua.edu.cn/rubygems" rel="nofollow" target="_blank"&gt;http://mirrors.tuna.tsinghua.edu.cn/rubygems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4、华为云：&lt;a href="https://mirrors.huaweicloud.com/repository/rubygems/" rel="nofollow" target="_blank"&gt;https://mirrors.huaweicloud.com/repository/rubygems/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5、阿里云：&lt;a href="https://mirrors.aliyun.com/rubygems/" rel="nofollow" target="_blank"&gt;https://mirrors.aliyun.com/rubygems/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6、腾讯云：&lt;a href="https://mirrors.tencent.com/rubygems/" rel="nofollow" target="_blank"&gt;https://mirrors.tencent.com/rubygems/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;均已经通过 rails8 项目安装 gem 测试有效&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Fri, 29 Aug 2025 04:31:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/44255</link>
      <guid>https://ruby-china.org/topics/44255</guid>
    </item>
    <item>
      <title>开发一个类似 logdown 的博客网站 loglearn</title>
      <description>&lt;p&gt;一直很喜欢 logdown 的的代码展现方式，代码可以添加文件路径，能让初学者不迷路。所以搞了个类似的网站：网址：&lt;a href="http://loglearn.fun/" rel="nofollow" target="_blank"&gt;http://loglearn.fun/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/flchenhp/43c3a65a-97ce-43b4-b621-7103e63f4e16.png!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Sun, 06 Aug 2023 18:21:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/43260</link>
      <guid>https://ruby-china.org/topics/43260</guid>
    </item>
    <item>
      <title>用 Rails 开发的一个财报展示网站 - 财报营</title>
      <description>&lt;p&gt;用 rails 开发的一个财报展示网站 - 财报营：&lt;a href="https://caibaoying.fun/" rel="nofollow" target="_blank"&gt;https://caibaoying.fun/&lt;/a&gt;，欢迎大家浏览提出优化建议&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Mon, 12 Jun 2023 18:14:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/43169</link>
      <guid>https://ruby-china.org/topics/43169</guid>
    </item>
    <item>
      <title>用 social-share-button 给文章加个社交分享功能</title>
      <description>&lt;h2 id="原文链接，原文展示效果更佳哦～"&gt;&lt;a href="http://www.structuredwriting.fun/front/posts/%E7%94%A8social-share-button%E7%BB%99%E6%96%87%E7%AB%A0%E5%8A%A0%E4%B8%AA%E7%A4%BE%E4%BA%A4%E5%88%86%E4%BA%AB%E5%8A%9F%E8%83%BD" rel="nofollow" target="_blank" title=""&gt;原文链接，原文展示效果更佳哦～&lt;/a&gt;&lt;/h2&gt;&lt;h2 id="why：为什么要分享？"&gt;why：为什么要分享？&lt;/h2&gt;
&lt;p&gt;文章分享有以下几大好处：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;得到点赞鼓励，可以正循环促进自己坚持写作&lt;/li&gt;
&lt;li&gt;得到批评意见，可以进行针对性的改善，提升自己的写作能力&lt;/li&gt;
&lt;li&gt;如果是无理的谩骂，直接无视，也能锻炼一下自己的厚脸皮和抗击打能力&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what：功能效果是什么样子？"&gt;what：功能效果是什么样子？&lt;/h2&gt;
&lt;p&gt;点击文章里微信图标，弹出二维码界面：&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/image/image/13/image-1630165893483.png" title="" alt="file"&gt;&lt;/p&gt;

&lt;p&gt;用微信扫描二维码会用微信打开这篇文章，点右上角课选择分享到到朋友圈或者朋友。其他社交网站还支持微博，Facebook，Twitter 等等好多个。&lt;/p&gt;
&lt;h2 id="how：如何一步步实现？"&gt;how：如何一步步实现？&lt;/h2&gt;
&lt;p&gt;Rails 的魅力就在于很多功能，别人都已经帮你写好了，我们只需要拿来用就可以，不用什么都自己做～&lt;/p&gt;

&lt;p&gt;Rails 实现社交分享超简单，写好的 gem 叫&lt;a href="https://github.com/huacnlee/social-share-button" rel="nofollow" target="_blank" title=""&gt;social-share-button&lt;/a&gt;，下面我就一步一步完成吧～&lt;/p&gt;
&lt;h3 id="安装social-share-button这个gem"&gt;安装 social-share-button 这个 gem&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+ gem 'social-share-button'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行&lt;code&gt;bundle install&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="引入js和css"&gt;引入 js 和 css&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //= require bootstrap/modal
+ //= require social-share-button
+ //= require social-share-button/wechat
  //= require_tree .
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; +@import "social-share-button";

  .....
  .....
+/****** 分享按钮样式 ******/
 +$size: 24px;
 +
 +.social-share-button {
 +  .ssb-icon {
 +    background-size: $size $size;
 +    height: $size;
 +    width: $size;
 +  }
 +}
 +/****** 完成分享按钮样式 ******/
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="给分享功能做配置"&gt;给分享功能做配置&lt;/h3&gt;
&lt;p&gt;执行&lt;code&gt;touch config/initializers/social_share_button.rb&lt;/code&gt;，新增配置文件&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SocialShareButton.configure do |config|
  config.allow_sites = %w(weibo qq wechat douban twitter facebook)
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你也可以自定义选择你希望分享的社交网站，具体参考：&lt;a href="https://github.com/huacnlee/social-share-button" rel="nofollow" target="_blank" title=""&gt;github 的说明文件&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="在post的show页面中增加分享的链接图标"&gt;在 post 的 show 页面中增加分享的链接图标&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= social_share_button_tag(@post.title, 'data-wechat-title' =&amp;gt; '#{@post.title}') %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="验证效果"&gt;验证效果&lt;/h3&gt;
&lt;p&gt;可以找个文章的 show 页面，点击尝试分享。&lt;/p&gt;

&lt;p&gt;大功告成，啦啦啦～&lt;/p&gt;
&lt;h2 id="参考文章"&gt;参考文章&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://kerzzi.logdown.com/posts/1951301" rel="nofollow" target="_blank" title=""&gt;「从零开始做购物网站」第 26 章 实作商品社交分享功能&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/huacnlee/social-share-button" rel="nofollow" target="_blank" title=""&gt;gem 的 github 链接&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>flchenhp</author>
      <pubDate>Sun, 29 Aug 2021 10:46:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/41632</link>
      <guid>https://ruby-china.org/topics/41632</guid>
    </item>
    <item>
      <title>新上线 Rails 网站的 SEO 优化要点</title>
      <description>&lt;h2 id="原文链接，原文展示效果更佳哦～"&gt;&lt;a href="http://www.structuredwriting.fun/front/posts/%E6%96%B0%E4%B8%8A%E7%BA%BFrails%E7%BD%91%E7%AB%99%E7%9A%84seo%E4%BC%98%E5%8C%96%E8%A6%81%E7%82%B9" rel="nofollow" target="_blank" title=""&gt;原文链接，原文展示效果更佳哦～&lt;/a&gt;&lt;/h2&gt;&lt;h2 id="什么是SEO"&gt;什么是 SEO&lt;/h2&gt;&lt;h3 id="新网站上线的下一个课题"&gt;新网站上线的下一个课题&lt;/h3&gt;
&lt;p&gt;当你的网站开发辛辛苦苦开发上线了，你的会遇到的下一个问题是如何推广，如何让用户发现有你这么个网站，解决思路主要有：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;出钱去做推广，比如出钱在百度上买某些关键字，用户在搜索这些关键字的时候就会优先把你的网站展现出来，但是用 rails 开发的主要都是创业公司，每一分钱都很宝贵。&lt;/li&gt;
&lt;li&gt;SEO 是另一个解决思路，SEO 的全名是（Search Engine Optimization），也就是让自己的网站符合搜索引擎的规则，提高网站权重，理想目标是能夠在搜尋页面前几笔就能被曝光。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="SEO权重要点"&gt;SEO 权重要点&lt;/h3&gt;
&lt;p&gt;虽然 SEO 的权重规则基本上一直在变化，权重的給分也随着技术升级而有了新的规则，像以往的网站只是网站，現在的网站还要能能够支持 RWD（responsive web design 响应式网站设计）來让移动端的浏览时能够更加轻松，也免去了做 mobile app 的工作（有能力两个都做当然更好）。&lt;/p&gt;

&lt;p&gt;搜索引擎如 google 会定时派爬虫來爬网站，爬完之后依照权重重新去排名，权重大致上要在乎的就是几点：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;善用 Meta Tag / Meta Data 帮网址划重点&lt;/li&gt;
&lt;li&gt;Url 具有意义&lt;/li&gt;
&lt;li&gt;HTML tag 沒有乱用，例如一大堆 h1&lt;/li&gt;
&lt;li&gt;采用 HTTPS 连接&lt;/li&gt;
&lt;li&gt;支持 RWD（Responsive Web Design）&lt;/li&gt;
&lt;li&gt;网站开启速度快&lt;/li&gt;
&lt;li&gt;语系和国家&lt;/li&gt;
&lt;li&gt;Sitemap&lt;/li&gt;
&lt;li&gt;爬虫&lt;/li&gt;
&lt;li&gt;浏览量&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="SEO优化参考标准"&gt;SEO 优化参考标准&lt;/h2&gt;&lt;h3 id="Meta Tag / Meta Data优化"&gt;Meta Tag / Meta Data 优化&lt;/h3&gt;
&lt;p&gt;Title Tag: 当前页面的标题，关键字要往前放，字数不宜过长，否則有可能被认为是权重作弊，建议&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;英文字数 70 以內&lt;/li&gt;
&lt;li&gt;中文字数 40 以內&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;范例：&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt; Rails 好用常用的gem汇总 | 结构化写作网&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Meta Description Tag: 每个页面的敘述，文案好坏间接影响点阅率&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;含标点符号的英文在 150 字內&lt;/li&gt;
&lt;li&gt;中文十二字內，关键字往前放&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;范例：&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"rails社区丰富的gem，是帮助rails工程师快速、快乐开发的好帮手，其中好用常用的已帮大家收集"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上兩個标签非常重要，每一個頁面一定要不一樣，如果过多重复，搜索引擎会认为你在作弊，是会扣分的哦&lt;/p&gt;

&lt;p&gt;如：Facebook Open Graph: 这是专门給 Facebook 抓取用的，可以在这些 meta tag 里面调整你要分享出去的內容长什麼樣子，如果都沒有设定，他会默认抓取你的 title description tag 來作为参考。&lt;/p&gt;

&lt;p&gt;可以用 Facebook debug tools 來作为侦查改善的工具&lt;/p&gt;

&lt;p&gt;Facebook 分享缩略图设定范例：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;meta property="og:image" content="https://example.me/img/about.jpg"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Twitter Cards: 这个就是专门给 Twitter 抓的，一样可以调整分享后的的样式。&lt;/p&gt;

&lt;p&gt;在 Rails 實作部分可以用&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;seo_helper&lt;/li&gt;
&lt;li&gt;meta-tags&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="网址优化"&gt;网址优化&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Canonical Url&lt;/strong&gt;
告诉搜索引擎关于这个页面的标准网址，有时候我們一个页面会带很多参数，可能是语系、搜索参数等等，這個标签可以让搜索引擎只收录正确的网址就可以了。&lt;/p&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://www.example.com/products?category=dresses&amp;amp;color=green&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;后面就带了 category 和 color 的传递参数，这样的网址看起來会非常不舒服。&lt;/p&gt;

&lt;p&gt;那么 Canonical Url 这个 tag 就可以这样写：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;link rel="canonical" href="https://www.example.com/products" /&amp;gt;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这样子就不会把一些带有参数的网址收录到搜索引擎下了&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;让 URL 具有意义&lt;/strong&gt;
禁用链接，如果有一些链接你不想被计入 SEO，那么你可以使用 nofollow 标签。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://support.google.com/webmasters/answer/96569?hl=zh-Hant" rel="nofollow" target="_blank" title=""&gt;關於 nofollow 介绍&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;情況大概会是，付费链接、留言里的链接，或是登入登出这种沒有必要被收入的链接会用到&lt;/p&gt;

&lt;p&gt;范例：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;link_to "不想被收录", awesome_path, rel: 'nofollow'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;在一般 CRUD 出來的网址，通常都会是&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://example.com/products/1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;那这个产品的 URL 是用数据库的 ID 作为依据，这样以来光看 URL 是沒有任何意义的，也无法提升权重，比较好的作法是让网址具有意义&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://example.com/products/aeron-chair http://example.com/products/xbox-360-white&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这样一來，不仅一眼就能够看得出來这个 product 是什么，也能提升搜索的权重。&lt;/p&gt;

&lt;p&gt;怎么做呢？&lt;/p&gt;

&lt;p&gt;在 Rails 上面可以使用 &lt;a href="https://github.com/norman/friendly_id" rel="nofollow" target="_blank" title=""&gt;friendly_id&lt;/a&gt; 这个 Gem，&lt;/p&gt;

&lt;p&gt;详细的实作我在之前有写过一篇 &lt;a href="https://blog.niclin.tw/2016/06/04/%E4%BD%BF%E7%94%A8-friendly_id-%E8%88%87-babosa-%E7%BE%8E%E5%8C%96%E4%BD%A0%E7%9A%84rails-%E7%B6%B2%E5%9D%80/" rel="nofollow" target="_blank" title=""&gt;使用 Friendly_id 与 Babosa 美化你的 Rails 网址&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在这里面的教学還可以让 URL 带中文的 slug。&lt;/p&gt;

&lt;p&gt;几点需要注意的是，如果要提升网域的权威性，请在主网域使用 例如：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://example.com/products/aeron-chair&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会比&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://shop.example.com/products/aeron-chair&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;来的更好，因为他可以直接提升 &lt;code&gt;http://example.com&lt;/code&gt; 的网域分数。&lt;/p&gt;
&lt;h3 id="HTML标签优化"&gt;HTML 标签优化&lt;/h3&gt;
&lt;p&gt;慎用 HTML tag，HTML tag 如果乱用，例如在同一个页面有一大堆 h1，是相当扣分的行为。&lt;/p&gt;

&lt;p&gt;因为 HTML tag 其实就是拿来替你的网页画清楚重点，他是一個&lt;strong&gt;具有意义的語言&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTML 当初在设计时，本身就带有「语意」&lt;/p&gt;

&lt;p&gt;你可以这样理解&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;h1 是大标题&lt;/li&gt;
&lt;li&gt;h2, h3 是中标题&lt;/li&gt;
&lt;li&gt;h4, h5, h6 是小标题&lt;/li&gt;
&lt;li&gt;p 是指 paragraph (段落)&lt;/li&gt;
&lt;li&gt;strong 是重点部分，他与 b 不同的是，b 只有粗体，但 strong 是加重语气，如果是盲人使用阅读器在观看你的网站时，加重语气可以让辅助导读的软体能够正确的念出这段话&lt;/li&gt;
&lt;li&gt;img 中的 alt 是指替代文字，title 是标题&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;开发者希望他的网站能正确被收录，那么你就应该正确的使用 HTML 语意标签。&lt;/p&gt;

&lt;p&gt;补充一点，&lt;/p&gt; 是对 SEO 沒有特別的加分或扣分效果，因为从以前就很流行以 div + CSS 来达到网站前端画面开发，毕竟 div 沒什麼包袱，它就是个区块

&lt;p&gt;所以 &lt;/p&gt;
 与 &lt;span&gt; 是沒有语意的，他只是容器

&lt;p&gt;规则标准：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;h1 一个页面只能有 1 个&lt;/li&gt;
&lt;li&gt;h2 一個页面只能有 2~3 个&lt;/li&gt;
&lt;li&gt;h3 一個页面可以有 6~10 个&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTML 标签权重由高至低：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;title &amp;gt; meta description &amp;gt; h1 &amp;gt; h2 &amp;gt; h3 &amp;gt; strong &amp;gt; p&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="连接安全优化"&gt;连接安全优化&lt;/h3&gt;
&lt;p&gt;优先采用 HTTPS 连线&lt;/p&gt;

&lt;p&gt;因为近年來非常重视资讯安全问题，尤其现在很多金流行为是可以透过网址传输完成的，这当中可能会有信用卡等交易的机密资料，那么用 HTTPS 可以避免被第三方监听，因为这个过程是加密传输的。&lt;/p&gt;

&lt;p&gt;HTTPS 是指你的网址有沒有安裝 SSL（Secure Sockets Layer , 传输层安全协议），如果你有确实安裝 SSL 的认证，通訊协定就会从 HTTP 改变为 HTTPS（Hypertext Transfer Protocol Secure , 超文字安全传输协议）。&lt;/p&gt;

&lt;p&gt;在 2014 年時，Google 官方正式宣布 HTTPS 已被列入搜索引擎演算法之一&lt;/p&gt;

&lt;p&gt;但如果你的网站只是「內容型网站」，沒有涉及到用户资安问题（例如交易），就目前來说，不使用 HTTPS 并不会有「超大的影响」。&lt;/p&gt;

&lt;p&gt;不过值得注意的是，从 2017 年 10 月起，从 Chrome 62 开始，只要是需要输入任何资料的网页，若未使用 HTTPS，即会被标示为不安全。&lt;/p&gt;

&lt;p&gt;參考 Google Chrome 官方文章&lt;/p&gt;

&lt;p&gt;也因为 SSL 的凭证基本上都是要钱的，但也有很好心的公司 &lt;a href="https://letsencrypt.org/" rel="nofollow" target="_blank" title=""&gt;Let’s Encrypt&lt;/a&gt; 大力推广加密凭证的安全，也有放出三個月免费的版本，过期的话就要重新签名。&lt;/p&gt;

&lt;p&gt;申请凭证的流程大致上是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;先自己生成一个私钥、一个申请用的凭证 CSR&lt;/li&gt;
&lt;li&gt;將 CSR 传上去给凭证机构&lt;/li&gt;
&lt;li&gt;凭证机构审核你真的拥有这个网域&lt;/li&gt;
&lt;li&gt;下载 SSL 凭证&lt;/li&gt;
&lt;li&gt;將私钥和 SSL 凭证安裝到网站服务器上&lt;/li&gt;
&lt;li&gt;如果主要客戶不是在中国，那么可以更简单的申请使用 Cloudflare 这个 CDN 服务，這包含免費的 SSL 憑證，可以免去申請安裝的麻煩。它的 Flexible SSL 模式，可以让終端使用者到 CloudFlare 是加密连线，而你的服务器不需要安裝。使用 Cloudflare 需要將 DNS 也給它管理，在注册的流程中会要求你去修改 Namecheap 改用 Custom DNS。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="支持 RWD响应式网页设计"&gt;支持 RWD 响应式网页设计&lt;/h3&gt;
&lt;p&gt;做 RWD 的好处是可以保有连接单一性，让原本的流量不会因为移动设备而沖散，因为这个链接的浏览量会让他的权重变高，更容易出現在搜索排名上面，但如果分別做 mobile/desktop 版，就会有两种不同的网址链接，会让 SEO 的效果打折。&lt;/p&gt;

&lt;p&gt;RWD，也不是有做就好，而是会去依照载入速度有不一样的评分。&lt;/p&gt;

&lt;p&gt;详细可以到&lt;a href="https://testmysite.thinkwithgoogle.com/" rel="nofollow" target="_blank" title=""&gt; Google 提供的简易测试工具&lt;/a&gt;来测试一下你的读取秒数吧，依照 Google 說法是人的耐性只有三秒 XD，那就尽可能的压到 3 秒以下吧 XDrz。&lt;/p&gt;
&lt;h3 id="网站开启速度"&gt;网站开启速度&lt;/h3&gt;
&lt;p&gt;通常一个网站会慢多半不是后端处理 query 的速度，都会是在前端资源情況吃太紧，既然要作最佳化就必須要用科学化的方式测量，这样一来我们才知道最佳化有沒有成功。&lt;/p&gt;

&lt;p&gt;Chrome 的除错器本身就很详细，可以观察 Network 在 Load page 花了多长的时间。&lt;/p&gt;

&lt;p&gt;对前端来说，重视的是 Page load time, 而不是单一 request 的时间，因为网页的组成有 HTML + CSS + JavaScript&lt;/p&gt;

&lt;p&gt;Google 提供的好用工具 &lt;a href="https://developers.google.com/speed/pagespeed/insights/" rel="nofollow" target="_blank" title=""&gt;PageSpeed Insights&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/speed/docs/insights/rules" rel="nofollow" target="_blank" title=""&gt;PageSpeed Insight 评分标准&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;或是用 Chrome 外挂&lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="nofollow" target="_blank" title=""&gt; Lighthouse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;都有清楚的报表以及提示你如何改善。&lt;/p&gt;

&lt;p&gt;知识点，在 HTTP2 以后，有 async 和 defer 属性可以用。&lt;/p&gt;

&lt;p&gt;以往的关键渲染会是把  javascript 移出 head, 让 CSS 优先加载达到画面快速渲染，在载入能够有互动式效果的 JS file。&lt;/p&gt;

&lt;p&gt;不过新的属性可以让浏览器知道要异步加载&lt;/p&gt;

&lt;p&gt;例如&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;-  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
+  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:async&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或是&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;-  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
+  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:defer&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;async 与 defer 差別在于&lt;/p&gt;

&lt;p&gt;async, 浏览器不会阻挡 HTML 渲染，当 JavaScript 下载完成时就会自动加载，不会等 HTML DOM 加载
defer, 浏览器也不会阻挡 HTML 渲染，但是当 JavaScript 下载完成后，会等 HTML 加载完成，才会执行 JavaScript。如果你的 JavaScript 里面有依赖 DOM 的話，适合用这个方式。
CSS 也被浏览器视为一种 render blocking 的资源，当浏览器解析 HTML 看到 &lt;code&gt;&amp;lt;link href="style.css" rel="stylesheet"&lt;/code&gt; 时，就会等待完整解析这个 CSS 后才会继续渲染頁面。&lt;/p&gt;
&lt;h3 id="语系与国家"&gt;语系与国家&lt;/h3&gt;
&lt;p&gt;如果你的网站本身有支援多语系，那么沒有设定好的情況会变成说，不论哪个国家的搜索引擎搜到你，进来都还要自己調整语系，而且在 google 搜寻结果上面也会 bian 得怪异，例如：美國 IP 搜出來的标题是中文之类的。&lt;/p&gt;

&lt;p&gt;所以別忘記在你的 html tag 裡面加入&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;html lang="zh"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;可以参考 Apple 官方网站的作法，该网站是很标准的能够支援多语系 SEO 的写法，具体如下&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.apple.com/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.apple.com/"&lt;/span&gt; &lt;span class="na"&gt;hreflang=&lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.apple.com/ae-ar/"&lt;/span&gt; &lt;span class="na"&gt;hreflang=&lt;/span&gt;&lt;span class="s"&gt;"ar-AE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.apple.com/ae/"&lt;/span&gt; &lt;span class="na"&gt;hreflang=&lt;/span&gt;&lt;span class="s"&gt;"en-AE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.apple.com/am/"&lt;/span&gt; &lt;span class="na"&gt;hreflang=&lt;/span&gt;&lt;span class="s"&gt;"en-AM"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样就能够让搜索引擎正确在每个国家直接显示相对应语系的网站了。&lt;/p&gt;

&lt;p&gt;这个方法不是唯一，你也可以选择用 &lt;a href="https://support.google.com/webmasters/answer/183668?hl=zh-Hant&amp;amp;ref_topic=8476" rel="nofollow" target="_blank" title=""&gt;Sitemap&lt;/a&gt; 的方法來让搜索引擎正确收录。&lt;/p&gt;

&lt;p&gt;择一即可。&lt;/p&gt;
&lt;h3 id="制定Sitemap"&gt;制定 Sitemap&lt;/h3&gt;
&lt;p&gt;Sitemap 基本是描述一个网站的架构，它可以是任意形式的网页页面，通常是采用分级或分类的形式，能够消化庞大的网站架构，对于网站的访问者在网站浏览上的资讯需求也能快速获得，且能提高 SEO 搜索引擎优化的效果，对网站的帮助是非常大。&lt;/p&gt;

&lt;p&gt;参考 &lt;a href="https://www.apple.com/tw/sitemap/" rel="nofollow" target="_blank" title=""&gt;Apple 繁体中文官网的 Sitemap&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在这部份用 Gem“&lt;a href="https://github.com/kjvarga/sitemap_generator" rel="nofollow" target="_blank" title=""&gt;sitemap_generator&lt;/a&gt;”可以轻松帮你完成，并且有 rake task 能够让你每次产生新內容的時候更新上去。&lt;/p&gt;
&lt;h3 id="爬虫"&gt;爬虫&lt;/h3&gt;
&lt;p&gt;在 Rails 的路径&lt;code&gt;public/robots.txt&lt;/code&gt; 是专门拿來給搜索引擎爬虫读取的，这只档案会告诉他什么资源不需要被收录。&lt;/p&gt;

&lt;p&gt;参考 &lt;a href="https://www.apple.com/robots.txt" rel="nofollow" target="_blank" title=""&gt;Apple 官方网站的 robots.txt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;不过有时候我们除了 Production 环境以外，可能还有 Staging，避免被收录的化可以依照环境动态生成 robots 这只档案。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get '/robots.txt' =&amp;gt; 'home#robots'
def robots                                                                                                                                      
  robots = File.read(Rails.root + "config/robots.#{Rails.env}.txt")
  render :text =&amp;gt; robots, :layout =&amp;gt; false, :content_type =&amp;gt; "text/plain"
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;分別在 &lt;code&gt;public/&lt;/code&gt;下生成&lt;code&gt;robots.staging.txt, robots.production.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;就可以做到根据环境控制生产 &lt;code&gt;robots.txt&lt;/code&gt;生成了&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/timcheadle/3761844" rel="nofollow" target="_blank" title=""&gt;參考 Gist&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="浏览量"&gt;浏览量&lt;/h3&gt;
&lt;p&gt;你的网域权重的提升也会因为浏览量的高低有不一样的排名，所以过时的导流进去，让更多用戶喜欢上这个产品能够不断回访网站，会让权重分数慢慢往上爬，這就跟养小孩一样，需要一点时间才会成长。&lt;/p&gt;

&lt;p&gt;Google 是会將大量的垃圾链接或不优质的內容降低权重的，所以非常重视网站经营者生成的內容，他们的演算法会一直更新，阻挡那些尝试作弊欺骗权重的网站，最后一点就是认真经营网站喽。&lt;/p&gt;
&lt;h2 id="參考資源"&gt;參考資源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.niclin.tw/2017/10/05/rails-%E9%96%8B%E7%99%BC%E7%B6%B2%E7%AB%99%E6%89%80%E9%9C%80%E7%9A%84-seo-%E5%AF%A6%E5%8B%99%E6%8A%80%E5%B7%A7/" rel="nofollow" target="_blank" title=""&gt;Rails 网站所需要的实务 SEO 技巧&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gogojimmy.net/2013/09/26/basic-seo-for-rails-developer/" rel="nofollow" target="_blank" title=""&gt;給 Rails Developer 的基本 SEO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.webdesigneer.com/sitemap-web-design" rel="nofollow" target="_blank" title=""&gt;[網頁設計] TOP10 網站地圖 Sitemap 案例介紹&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ittribalwo.com/article/922.html" rel="nofollow" target="_blank" title=""&gt;Canonical 标签的三点作用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://seo.dns.com.tw/archives/10633" rel="nofollow" target="_blank" title=""&gt;網站優化應該使用 Responsive Web Design 嗎？&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://awoo.ai/zh-hant/blog/site-speed-optimization/" rel="nofollow" target="_blank" title=""&gt;做 SEO 你絕對不可以忽略的【網站速度優化】，關於速度優化的三兩事&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/span&gt;

</description>
      <author>flchenhp</author>
      <pubDate>Sat, 28 Aug 2021 18:40:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/41630</link>
      <guid>https://ruby-china.org/topics/41630</guid>
    </item>
    <item>
      <title>推荐一个 Rails 网站作品</title>
      <description>&lt;p&gt;自学 rails，开发的一个 rails 网站作品，结构化写作网，&lt;a href="http://www.structuredwriting.fun/" rel="nofollow" target="_blank"&gt;http://www.structuredwriting.fun/&lt;/a&gt;，大家看看是什么水平&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Fri, 27 Aug 2021 17:25:22 +0800</pubDate>
      <link>https://ruby-china.org/topics/41625</link>
      <guid>https://ruby-china.org/topics/41625</guid>
    </item>
    <item>
      <title>Rails 好用常用 gem 汇总</title>
      <description>&lt;h2 id="原文链接,原文展示效果更佳哦～"&gt;&lt;a href="http://www.structuredwriting.fun/front/posts/rails-%E5%A5%BD%E7%94%A8%E5%B8%B8%E7%94%A8gem%E6%B1%87%E6%80%BB" rel="nofollow" target="_blank" title=""&gt;原文链接，原文展示效果更佳哦～&lt;/a&gt;&lt;/h2&gt;&lt;h2 id="好用的 Gem 列表"&gt;好用的 Gem 列表&lt;/h2&gt;
&lt;p&gt;本页用于介绍 Ruby 社区里面那些特别热门的 Gem，以下 Gem 可以在 rubygems.org 找到。&lt;/p&gt;

&lt;p&gt;实用的 RubyGems 排名站点 &lt;a href="www.ruby-toolbox.com" title=""&gt;www.ruby-toolbox.com&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="前端常用"&gt;前端常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/twbs/bootstrap-rubygem" rel="nofollow" target="_blank" title=""&gt;bootstrap&lt;/a&gt;
来自 Twitter 的 Bootstrap，是一套完成的前台 CSS 框架。以简洁，优雅著称于世。被无数攻城狮所青睐，又让无数程序猿审美疲劳。&lt;/p&gt;

&lt;p&gt;font-awesome-sass
icon 图标&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/heartcombo/simple_form" rel="nofollow" target="_blank" title=""&gt;simple_form&lt;/a&gt; 和 &lt;a href="https://github.com/formtastic/formtastic" rel="nofollow" target="_blank" title=""&gt;Formtastic&lt;/a&gt;
Rails 为我们带来和一改传统的表单构件方式，但是经过实际的使用，我们渐渐发觉这样依然还是不够“敏捷”，我们需要更加简便并具有更细致规范的表单，所以有了 Formtastic，它用起来比 Rails 默认的 form 更加简洁，但是却具有更多的功能，你可以为每个字段设定 help-text 放到文本框下面，并可以走 I18n 的方式设置语言，具体参见 Railscasts 上面对于 Formtastic 的介绍。而 simple_form 和 Formtastic 功能类似，但它的写法还要简单一些。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/DavyJonesLocker/client_side_validations" rel="nofollow" target="_blank" title=""&gt;ClientSideValidations&lt;/a&gt;
现在越来越多网站为了改善用户体验，使用 JavaScript 来进行客户端验证。对于程序员来说，也因此增加多一份工作。而往往客户端的验证逻辑跟服务端的验证逻辑几乎一样，如果要另外再写一次验证代码，实在不够 DRY，client_side_validations 正是为解决此问题要出现。client_side_validations 会读取服务端的验证逻辑并生成对应的客户端验证逻辑（依赖 jQuery），让你几乎不用增加任何前端代码就可实现客户验证。&lt;/p&gt;

&lt;p&gt;bootstrap-datepicker-rails
bootstrap 风格的日历&lt;/p&gt;

&lt;p&gt;select2-rails:  下拉提示 select 框（支持前端和后端）&lt;/p&gt;
&lt;h3 id="会员系统常用"&gt;会员系统常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/heartcombo/devise" rel="nofollow" target="_blank" title=""&gt;Devise&lt;/a&gt;
用于快速构建用户功能，如：注册，登陆，个人设置，找回密码... 同时 Ruby 社区有各类和账号体系的库可以很容易和 Devise 打通。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/huacnlee/rucaptcha" rel="nofollow" target="_blank" title=""&gt;RuCaptcha&lt;/a&gt;
图片验证码，安全、简单、易用，无依赖。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/EppO/rolify" rel="nofollow" target="_blank" title=""&gt;rolify&lt;/a&gt;
Very simple Roles library without any authorization enforcement supporting scope on resource obje&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CanCanCommunity/cancancan" rel="nofollow" target="_blank" title=""&gt;CanCanCan&lt;/a&gt;
一些应用中会用到为不同用户设定不同功能的权限，你可以试试 CanCanCan 这个 Gem 他可以帮你制定一套完善的方案，Railscasts 上有使用介绍。&lt;/p&gt;

&lt;p&gt;如果 Devise 一样，CanCanCan 在 Ruby 社区也是非常流行，所以和它有关的实现非常多，你能很容易找到资料。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/omniauth/omniauth" rel="nofollow" target="_blank" title=""&gt;OmniAuth&lt;/a&gt;
如果你需要在项目中实现三方平台（如：Twitter, Facebook, 新浪微博，腾讯 QQ）账号登陆的支持，那你需要用上它。&lt;/p&gt;

&lt;p&gt;omniauth-weibo-oauth2
omniauth-qq-connect
omniauth-wechat-oauth2&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/doorkeeper-gem/doorkeeper" rel="nofollow" target="_blank" title=""&gt;Doorkeeper&lt;/a&gt;
前面说了 OmniAuth 介入 OAuth 2 的服务，有时候你可能需要自己建立一个 OAuth 2 服务，作为提供商，这个时候 Doorkeeper 可以帮到你。&lt;/p&gt;

&lt;p&gt;china_sms：短信平台接口， &lt;a href="https://github.com/saberma/china_sms" rel="nofollow" target="_blank"&gt;https://github.com/saberma/china_sms&lt;/a&gt;
wechat-rails：帮助开发者方便地在 Rails 环境中集成微信公众平台提供的所有服务
rqrcode：生成二维码&lt;/p&gt;
&lt;h3 id="内容功能常用"&gt;内容功能常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/mislav/will_paginate" rel="nofollow" target="_blank" title=""&gt;will_paginate &lt;/a&gt;和 &lt;a href="https://github.com/amatsuda/kaminari" rel="nofollow" target="_blank" title=""&gt;Kaminari&lt;/a&gt;
分页，几乎所有 Rails App 都在用，其中 will_paginate 比较老，应用案例较多，kaminari 更新，性能和兼容性更好&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/carrierwaveuploader/carrierwave" rel="nofollow" target="_blank" title=""&gt;Carrierwave&lt;/a&gt; 和 &lt;a href="https://github.com/thoughtbot/paperclip" rel="nofollow" target="_blank" title=""&gt;Paperclip&lt;/a&gt;
这两个都是上传组件，Paperclip 是老牌产品了，也是几乎绝大多数项目都有在用它，它可以帮你处理上传图片，裁减，定义不同的图片尺寸，几乎很完美。而 Carrierwave 是后起之秀，功能和 Paperclip 差不多，但它还可以管理除图片之外的东西，而且灵活性更高（ruby-china 就是用它）。国内的各大云存储服务都已经有了 Carrierwave 的支持，例如 carrierwave-aliyun, carrierwave-upyun。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/leikind/wice_grid" rel="nofollow" target="_blank" title=""&gt;WiceGrid&lt;/a&gt;
表格控件，针对 ActiveRecord，超级强大，支持任意字段排序，过滤，具体看它的 Demo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/elastic/elasticsearch-rails" rel="nofollow" target="_blank" title=""&gt;elasticsearch-rails&lt;/a&gt;
实现全文搜索或搜索有关的功能，目前要数 Elasticsearch 最火，它也有 Ruby 的实现。&lt;/p&gt;

&lt;p&gt;Ransack&lt;br&gt;
常用的搜索插件&lt;/p&gt;

&lt;p&gt;social-share-button
分享功能&lt;/p&gt;

&lt;p&gt;ancestry 
树形结果的方式存储，可以看作是一对多、多对多的扩展 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/radar/by_star" rel="nofollow" target="_blank" title=""&gt;by_star&lt;/a&gt;
这是一个辅助 ActiveRecord 的组件，让你可以简单的实现按某年，某月，某日，或者星期几，来查询数据，用起来非常简单，省下麻烦的条件组合，此外，它还可以查询上一篇，下一篇类似的功能。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/michelson/lazy_high_charts" rel="nofollow" target="_blank" title=""&gt;lazy_high_charts&lt;/a&gt;
当前绘图 JS 库中 Highcharts 非常优秀，rubyist 使用这个 gem 来管理和编写需要的图。&lt;/p&gt;

&lt;p&gt;rmagick&lt;br&gt;
图片处理确保安装了 ImageMagick，rmagick 是 ImageMagick 的中间件，用于对图片进行切割等操作。mini-magick  稳定，占用内存小，但是功能比 rmagick 少&lt;/p&gt;

&lt;p&gt;acts_as_list
给 model 中的对象进行排序记录在 position 字段中&lt;/p&gt;

&lt;p&gt;chinese_pinyin 
转化汉字为拼音  eg: Pinyin.t("中国") =&amp;gt; "zhongguo"&lt;/p&gt;

&lt;p&gt;acts-as-taggable-on
管理标签的插件&lt;/p&gt;

&lt;p&gt;spreadsheet
操作电子表格&lt;/p&gt;

&lt;p&gt;china_city
省市区级联&lt;/p&gt;

&lt;p&gt;aasm 
ruby 状态机&lt;/p&gt;

&lt;p&gt;awesome_nested_set
Model 多层类别&lt;/p&gt;
&lt;h3 id="内容输入"&gt;内容输入&lt;/h3&gt;
&lt;p&gt;redcarpet
Markdown 标记语言&lt;/p&gt;
&lt;h3 id="后台管理"&gt;后台管理&lt;/h3&gt;
&lt;p&gt;active_admin
后台管理框架&lt;/p&gt;
&lt;h3 id="部署"&gt;部署&lt;/h3&gt;
&lt;p&gt;capistrano
项目自动化部署&lt;/p&gt;
&lt;h3 id="开发测试常用"&gt;开发测试常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/huacnlee/rails-settings-cached" rel="nofollow" target="_blank" title=""&gt;RailsSettingsCached&lt;/a&gt;
项目经常会有一些配置信息，你需要一个库帮你管理。&lt;/p&gt;

&lt;p&gt;annotate
在 model 类的顶部或者底部，插入数据库表的描述，方便查看&lt;/p&gt;

&lt;p&gt;faker
生成假数据&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pry/pry" rel="nofollow" target="_blank" title=""&gt;pry&lt;/a&gt;
简单强大的调试工具，轻量级的工具。直接在终端调试方便又直接&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/BetterErrors/better_errors" rel="nofollow" target="_blank" title=""&gt;Better Errors&lt;/a&gt;
它用一个更好的，更有用的错误页替换标准的 Rails 错误页面，对 Rack middleware 也同样有效。·Railscasts 也有相应的介绍。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mbleigh/seed-fu" rel="nofollow" target="_blank" title=""&gt;Seed Fu&lt;/a&gt;
强大的 seed&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ruby-grape/grape" rel="nofollow" target="_blank" title=""&gt;Grape&lt;/a&gt;
随着 Mobile App 的增多，很多时候我们在做用 Rails 做 API Base 项目时，rails 自带的 C 和 V 层显得过于繁杂，grape 可以帮助我们快速的构建和 Rails 完美融合的 API 接口。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lostisland/faraday" rel="nofollow" target="_blank" title=""&gt;Faraday&lt;/a&gt;
HTTP Client 支持多种方式&lt;/p&gt;

&lt;p&gt;rails_best_practices
编写代码总有方圆，费心费力写文档，还不如用这个工具来控制代码质量。&lt;/p&gt;

&lt;p&gt;daemon-spawn
将一些事情作为 daemon 来启动，可以类似 Debian 的 service foo start 比如 用来管理 Resque 的启动和重启，会变得很简单。&lt;/p&gt;

&lt;p&gt;rest-client：Http 客户端&lt;/p&gt;
&lt;h3 id="生产运维性能常用"&gt;生产运维性能常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/javan/whenever" rel="nofollow" target="_blank" title=""&gt;Whenever&lt;/a&gt;
Linux 里面有 Cron 可以帮助我们定期执行一些任务，但是 Cron 手动写起来很是麻烦，尤其是前面时间周期的定义，Whenever 可以帮助我们用更人性化的方式编写 Cron 任务，具体参见 Railscasts 上面关于 Whenever 的介绍。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mperham/sidekiq" rel="nofollow" target="_blank" title=""&gt;Sidekiq&lt;/a&gt;, &lt;a href="https://github.com/resque/resque" rel="nofollow" target="_blank" title=""&gt;Resque&lt;/a&gt; 和 &lt;a href="https://github.com/collectiveidea/delayed_job" rel="nofollow" target="_blank" title=""&gt;Delayed_job&lt;/a&gt;
有时候一些任务的执行会很慢，而这些任务我们并不要求需要马上返回结果 (比如：发送邮件，生成图片缩略图)，那我们可以选择将这些任务放到后台执行，以便于页面不会长时间等待执行。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://godrb.com/" rel="nofollow" target="_blank" title=""&gt;god&lt;/a&gt;
Ruby 进程监控工具&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hooopo/second_level_cache/" rel="nofollow" target="_blank" title=""&gt;second_level_cache&lt;/a&gt;
ActiveRecord 二级缓存插件，装上他你可以无缝的实现对 ActiveRecord 数据的二级缓存。&lt;/p&gt;

&lt;p&gt;paper_trail
记录 model 数据的变化&lt;/p&gt;
&lt;h3 id="爬虫常用"&gt;爬虫常用&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://nokogiri.org/" rel="nofollow" target="_blank" title=""&gt;Nokogiri&lt;/a&gt;
采集数据是我们需要解析复杂的 HTML 结构，从中获得需要的数据，Nokogiri 可以帮助我们完美的处理不同网页上面不同的 HTML 结构，并且有很好的编码处理能力，用它你不用担心页面是 GB2312 还是 GBK 还是 UTF-8，它都很很好的处理，解析结构可以用类似 jQuery 的 CSS Selector 的方式查找，很是方便。曾经用过 Ruby 的好几个类似插件，最终发现 Nokogiri 才是最好的。&lt;/p&gt;
&lt;h3 id="SEO优化"&gt;SEO 优化&lt;/h3&gt;
&lt;p&gt;sitemap_generator
生成网站的 sitemap.xml 文件&lt;/p&gt;
&lt;h2 id="参考文章"&gt;参考文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://ruby-china.org/wiki/gems" title=""&gt;ruby china 推荐 Ruby Gem 列表&lt;/a&gt;
&lt;a href="https://www.cnblogs.com/scige/archive/2012/12/10/2812093.html" rel="nofollow" target="_blank" title=""&gt;rails 常用插件&lt;/a&gt;
&lt;a href="https://ruby-china.org/topics/25872" title=""&gt;rubyChina 帖子回复&lt;/a&gt;&lt;/p&gt;</description>
      <author>flchenhp</author>
      <pubDate>Fri, 27 Aug 2021 11:45:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/41623</link>
      <guid>https://ruby-china.org/topics/41623</guid>
    </item>
  </channel>
</rss>
