📦 Dhh Rails Style — DHH Rails 风格 — 遵循 37signals 风格的 Ruby/Rails 编码指南
v0.1.0在编写 Ruby 与 Rails 代码时,采用 DHH 标志性的 37signals 风格:强调约定优于配置、追求简洁优雅、注重可读性与开发者幸福感,遵循 Rails 默认约定,减少冗余抽象,用清晰命名和 RESTful 设计传递意图,让代码像散文一样自然流畅。
详细分析 ▾
运行时依赖
版本
DHH Rails 风格技能的初始发布。- 提供 Ruby 和 Rails 项目(37signals/DHH 风格)的指导和代码审查。- 包括原则:优先使用原生 Rails、模型驱动、控制器简洁、REST 纯度、Current 属性、Hotwire/Turbo 模式和'清晰优于聪明'。- 提供命名、REST 资源映射、Ruby 习惯、DHH 首选模式的快速参考。- 描述使用和避免的内容(无 Devise、Sidekiq、Redis 等)。- 支持架构、测试、Gems、代码审查和一般 Rails 风格指导。
安装命令
点击复制技能文档
<目标> 应用 37signals/DHH Rails 约定到 Ruby 和 Rails 代码中。此技能提供了从分析生产级 37signals 代码库(Fizzy/Campfire)和 DHH 的代码审查模式中提取的综合领域专业知识。
<基本原则>
核心哲学
"最好的代码是你不写的代码。其次是显而易见的代码。"
原生 Rails 已经足够:
- 丰富的领域模型优于服务对象
- CRUD 控制器优于自定义操作
- Concerns 用于横向代码共享
- 记录作为状态而非布尔列
- 数据库支撑一切(不使用 Redis)
- 在求助 gem 之前先构建解决方案
他们刻意避免:
- devise(使用自定义的约 150 行认证替代)
- pundit/cancancan(模型中的简单角色检查)
- sidekiq(Solid Queue 使用数据库)
- redis(一切用数据库)
- view_component(partial 足够用)
- GraphQL(REST 配合 Turbo 足够用)
- factory_bot(fixtures 更简单)
- rspec(Rails 自带 Minitest)
- Tailwind(使用原生 CSS 和层)
开发哲学:
- 交付、验证、优化
- 原型质量的代码到生产环境以学习
- 修复根本原因,而非症状
- 写时操作优于读时计算
- 数据库约束优于 ActiveRecord 验证
<需求> 你在做什么?
- 控制器 - REST 映射、concerns、Turbo 响应、API 模式
- 模型 - Concerns、状态记录、回调、作用域、POROs
- 视图和前端 - Turbo、Stimulus、CSS、partials
- 架构 - 路由、多租户、认证、任务、缓存
- 测试 - Minitest、fixtures、集成测试
- Gems 和依赖 - 什么使用什么避免
- 代码审查 - 根据 DHH 风格审查代码
- 一般指导 - 哲学和约定
指定一个数字或描述你的任务。
<路由>
| 响应 | 参考阅读 |
|---|---|
| 1, controller | controllers.md |
| 2, model | models.md |
| 3, view, frontend, turbo, stimulus, css | frontend.md |
| 4, architecture, routing, auth, job, cache | architecture.md |
| 5, test, testing, minitest, fixture | testing.md |
| 6, gem, dependency, library | gems.md |
| 7, review | 阅读所有参考,然后审查代码 |
| 8, general task | 根据上下文阅读相关参考 |
<快速参考>
命名约定
动词: card.close、card.gild、board.publish(不是 set_style 方法)
谓词: card.closed?、card.golden?(从相关记录的存在派生)
Concerns: 描述能力的形容词(Closeable、Publishable、Watchable)
控制器: 匹配资源的名词(Cards::ClosuresController)
作用域:
chronologically、reverse_chronologically、alphabetically、latestpreloaded(标准预加载名称)indexed_by、sorted_by(参数化)active、unassigned(业务术语,而非 SQL 风格)
REST 映射
不创建自定义操作,而是创建新资源:
POST /cards/:id/close → POST /cards/:id/closure
DELETE /cards/:id/close → DELETE /cards/:id/closure
POST /cards/:id/archive → POST /cards/:id/archival
Ruby 语法偏好
# 带空格的符号数组在方括号内 before_action :set_message, only: %i[ show edit update destroy ]# 私有方法缩进 private
def set_message @message = Message.find(params[:id]) end
# 无表达式的 case 用于条件 case when params[:before].present? messages.page_before(params[:before]) else messages.last_page end
# bang 方法用于快速失败 @message = Message.create!(params)
# 三元运算符用于简单条件 @room.direct? ? @room.users : @message.mentionees
关键模式
状态即记录:
Card.joins(:closure) # 已关闭的卡片
Card.where.missing(:closure) # 开放的卡片
Current 属性:
belongs_to :creator, default: -> { Current.user }
模型上的授权:
class User < ApplicationRecord
def can_administer?(message)
message.creator == self || admin?
end
end
<参考索引>
领域知识
所有详细模式在 references/ 中:
| 文件 | 主题 |
|---|---|
| controllers.md | REST 映射、concerns、Turbo 响应、API 模式、HTTP 缓存 |
| models.md | Concerns、状态记录、回调、作用域、POROs、授权、广播 |
| frontend.md | Turbo Streams、Stimulus 控制器、CSS 层、OKLCH 颜色、partials |
| architecture.md | 路由、认证、任务、Current 属性、缓存、数据库模式 |
| testing.md | Minitest、fixtures、单元/集成/系统测试、测试模式 |
| gems.md | 什么使用什么避免、决策框架、Gemfile 示例 |
<成功标准> 代码符合 DHH 风格当:
- 控制器映射到资源上的 CRUD 动词
- 模型使用 concerns 实现横向行为
- 状态通过记录而非布尔值跟踪
- 没有不必要的服务对象或抽象
- 优先使用数据库解决方案而非外部服务
- 测试使用 Minitest 配合 fixtures
- 使用 Turbo/Stimulus 实现交互性(不使用重型 JS 框架)
- 使用现代特性的原生 CSS(层、OKLCH、嵌套)
- 授权逻辑位于 User 模型上
- 任务是调用模型方法的浅层包装
<致谢> 基于 The Unofficial 37signals/DHH Rails Style Guide,由 Marc Köhlbrugge 通过深入分析 Fizzy 代码库的 265 个拉取请求生成。
重要免责声明:
- 由 LLM 生成的指南 - 可能包含不准确之处
- Fizzy 的代码示例根据 O'Saasy 许可证授权
- 与 37signals 无关联或未获得其认可