← 所有文章

写了十年 Rails:那些我至今每天都在用的东西

这不是一篇框架评测,而是一份个人记录——哪些 Rails 模式经受住了时间考验,哪些没有,以及我仍然为之骄傲的几个项目。


我的第一个 Rails 应用是一场灾难。那年我 23 岁,刚跟着 Michael Hartl 的教程学完这个框架,就怀着”初生牛犊不怕虎”的自信搭了一个给音乐人用的社交平台。每个页面都有 N+1 查询,认证是自己手写的,部署是一个单 Heroku dyno,内存超过 512MB 就重启。

它勉强撑了几个月,然后在自身的重量下崩掉了。我是在生产环境里修问题的过程中,才真正搞懂了”性能”是什么意思。

那是十年前。从那以后我一直在职业地写 Rails——在初创公司,在 Ekohe,为零售、物流、人力资源和建筑行业的企业客户。以下是真正经受住考验的东西,以及我悄悄不再做的东西。

经住了时间考验的

Migrations(数据库迁移)。 我在职业生涯里用过十几个框架的数据库迁移工具,Rails 的 Migration 至今是我见过最好的。每个变更单独一个文件、updown 的分离(或者 change 的简便写法)、时间戳作为顺序标识——这套设计在我经手过的各种规模的项目上都好用。每次看其他生态的迁移工具,我脑子里总是拿它来比。

ActiveRecord 回调。 我知道,这个很有争议。社区曾经有一段时间流行一种论调——回调是邪恶的,所有逻辑都应该放进服务对象做显式编排。我试了一年,然后就开始想念 after_commit 了。对于真正属于模型生命周期的事件——审计日志、缓存失效、通知触发——回调正是合适的地方。问题不在于回调本身,而在于把本该在别处的业务逻辑塞进回调。

约定优于配置。 rails new 给你一个可以运行的应用,目录结构告诉你每样东西放哪儿,新加入 Rails 代码库的开发者几个小时内就能找到方向,而不是几天。在花了好几个月与配置即学科的框架打交道之后,我越来越清楚这种约定给团队带来的生产力价值。

资产管道(以及现在的 Propshaft/Importmap)。 前端世界变化很快。Rails 不得不跟着适应——从资产管道到 Webpacker,再到现在默认的 Importmap + Propshaft。适应的过程磕磕绊绊,但把前端资产作为应用一等公民这个底层理念,比”把一个独立前端 App 接到你的 API 上”存活得更久。

我不再做的事

到处都是服务对象。 这是 Rails 讨论里一个特定的历史时期——大概 2015 到 2020 年——那时的建议是把所有业务逻辑提取成”Plain Old Ruby Objects”,叫做服务对象。UserRegistrationServiceOrderFulfillmentServiceReportGeneratorService

有些服务对象是合理的,大多数只是把复杂度从一个文件挪到了另一个文件,没有让它变简单。我看过一个控制器 action 调用五个服务对象,然后意识到它比等价的”胖模型”写法更难理解。现在我只在模型会因此承担太多不同职责时才用服务对象——而不是作为所有事情的默认模式。

Decorator 替代 Partial。 Decorator 模式在 Rails 里有合理的使用场景——Draper 曾经很流行。但给每个对象套一层 Wrapper 来添加展示逻辑,大多数情况下代价超过收益。控制器里的 helper_method 加上组织得当的 Partial,能覆盖绝大多数场景,而且没有那层间接性。

在尝试 Devise 之前自己写认证。 最初两年我总是自己写认证,因为我想理解底层原理。那是有价值的练习,做过一次就够了。现在除非有特别的理由,我都用 Devise 或者更新的 authentication-zero 生成器。底层原理没有变,但我的时间现在有更值得花的地方。

我仍然为之骄傲的项目

WorkflowPro:为一家电梯制造企业开发的办公自动化系统,包含审批工作流、HR 集成和文档管理,服务 200 多名员工,零计划外停机运行了三年。让我骄傲的不是功能本身,而是数据模型。我们在第一次设计会议上就把领域模型定对了,在需求不断演进的过程中没有做过重大调整。

电梯行业 ERP:多租户 Rails 系统,带项目管理、合同跟踪和财务报表。2019 年我开发的,现在还在生产环境跑着。这个代码库比现在维护它的工程师入行时间还长。最让我满意的结果是它的可维护性——一个新开发者一周之内就能搞懂它。

Ekohe 内部搜索平台:Elasticsearch 集成到 Rails API,对几百万文档做分面搜索。不算炫技,但搞对了技术上很让人满足。索引管道和查询构建器,至今是我写过设计最精心的代码之一。

我现在还用 Rails 做什么

复杂的、数据驱动的应用,带有多种用户角色、审批工作流、审计追踪和外部系统集成。电商后端。移动应用的 API 后端。运营团队用的管理后台。

我不用 Rails 做的事:需要实时协作的应用(这里 Phoenix/Elixir 更适合)、纯粹的无服务器函数、服务器只负责提供数据 API 而前端高度复杂的 SPA。

这个框架已经 20 年了,它依然是我面对一大类问题时的首选。这不是怀旧,只是选了正确的工具。

Encore Shao

全栈工程师 & AI 研究员,就职于上海 Ekohe。10 年以上经验,专注于 Rails 应用与 Agentic AI 系统。