name: dhh-rails-style description: 该技能应用于以 DHH 独特的 37signals 风格编写 Ruby 和 Rails 代码时。适用于编写 Ruby 代码、Rails 应用程序、创建模型、控制器或任何 Ruby 文件。在 Ruby/Rails 代码生成、重构请求、代码审查或用户提到 DHH、37signals、Basecamp、HEY 或 Campfire 风格时触发。体现了 REST 纯净、胖模型瘦控制器、Current 属性、Hotwire 模式以及“清晰优于巧妙”的哲学。
<objective> 将 37signals/DHH Rails 惯例应用于 Ruby 和 Rails 代码。该技能提供通过分析生产 37signals 代码库(Fizzy/Campfire)和 DHH 的代码审查模式提取的全面领域专业知识。 </objective>
<essential_principles>
核心哲学
“最好的代码是你不需要写的代码。第二好的是明显正确的代码。”
原生 Rails 足够:
- 丰富的领域模型优于服务对象
- CRUD 控制器优于自定义操作
- 使用 Concerns 进行水平代码共享
- 记录作为状态而不是布尔列
- 数据库支持一切(不使用 Redis)
- 构建解决方案而非依赖 gem
他们刻意避免的:
- devise(使用自定义约150行认证替代)
- pundit/cancancan(模型中简单的角色检查)
- sidekiq(使用数据库的 Solid Queue)
- redis(一切使用数据库)
- view_component(部分视图工作良好)
- GraphQL(REST 与 Turbo 足够)
- factory_bot(固定数据更简单)
- rspec(Rails 自带 Minitest)
- Tailwind(原生 CSS 与层)
开发哲学:
- 发布、验证、精炼——将原型质量代码部署到生产以学习
- 修复根本原因,而非症状
- 写时操作优于读时计算
- 数据库约束优于 ActiveRecord 验证 </essential_principles>
<intake> 你在做什么?
- 控制器 - REST 映射、Concerns、Turbo 响应、API 模式
- 模型 - Concerns、状态记录、回调、作用域、POROs
- 视图与前端 - Turbo、Stimulus、CSS、部分视图
- 架构 - 路由、多租户、认证、作业、缓存
- 测试 - Minitest、固定数据、集成测试
- Gem 与依赖 - 使用什么与避免什么
- 代码审查 - 根据 DHH 风格审查代码
- 一般指导 - 哲学和惯例
指定数字或描述你的任务。 </intake>
<routing>
| 响应 | 参考阅读 |
|---|---|
| 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 | 基于上下文阅读相关参考 |
阅读相关参考后,将模式应用于用户代码。 </routing>
<quick_reference>
命名惯例
动词: 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
# 失败快速的方法使用感叹号
@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
</quick_reference>
<reference_index>
领域知识
所有详细模式在 references/:
| 文件 | 主题 |
|---|---|
| controllers.md | REST 映射、Concerns、Turbo 响应、API 模式、HTTP 缓存 |
| models.md | Concerns、状态记录、回调、作用域、POROs、授权、广播 |
| frontend.md | Turbo Streams、Stimulus 控制器、CSS 层、OKLCH 颜色、部分视图 |
| architecture.md | 路由、认证、作业、Current 属性、缓存、数据库模式 |
| testing.md | Minitest、固定数据、单元/集成/系统测试、测试模式 |
| gems.md | 他们使用什么与避免什么、决策框架、Gemfile 示例 |
| </reference_index> |
<success_criteria> 代码遵循 DHH 风格当:
- 控制器映射到资源的 CRUD 动词
- 模型使用 Concerns 进行水平行为
- 状态通过记录而非布尔值跟踪
- 无不必要的服务对象或抽象
- 优先数据库支持解决方案而非外部服务
- 测试使用 Minitest 与固定数据
- 使用 Turbo/Stimulus 进行交互性(无重 JS 框架)
- 原生 CSS 与现代特性(层、OKLCH、嵌套)
- 授权逻辑位于 User 模型
- 作业是调用模型方法的浅包装器 </success_criteria>
<credits> 基于 The Unofficial 37signals/DHH Rails Style Guide 由 Marc Köhlbrugge,通过深度分析 Fizzy 代码库的 265 个拉取请求生成。
重要免责声明:
- LLM 生成的指南——可能包含不准确之处
- Fizzy 的代码示例根据 O’Saasy 许可证许可
- 与 37signals 无关联或背书 </credits>