rails-principles-and-boundaries
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRails Principles and Boundaries
Rails 原则与边界规范
Use this skill when writing or reviewing Rails application code where design principles and per-area rules matter more than stack-specific UI choices (see rails-stack-conventions for Hotwire + Tailwind).
Style source of truth: Style and formatting follow whatever linter(s) the project configures (see Linter — initial analysis below). This skill adds non-style behavior and architecture guidance only.
当你编写或评审Rails应用代码,且设计原则和分领域规则比技术栈特定的UI选择更重要时,可使用本指南(Hotwire + Tailwind相关规范请参考rails-stack-conventions)。
风格权威依据: 代码风格与格式完全遵循项目配置的linter规则(请参考下方的「Linter - 初始分析」章节)。本指南仅补充非风格类的行为规范和架构指导。
Linter — initial analysis
Linter - 初始分析
Before recommending style fixes or contradicting formatting rules:
- Detect which linter(s) the repo uses — e.g. RuboCop (,
.rubocop.ymlinrubocop), Standard Ruby (Gemfile,standardrbgem), frontend linters (standard,eslint.config.*,.eslintrc*, etc.), or scripts inbiome.json/package.json(bin/,lint,rubocop).standardrb - Run the command the project documents or that matches the config (e.g. ,
bundle exec rubocop,bundle exec standardrb). Do not assume RuboCop if the project uses Standard or another stack.npm run lint
在推荐风格修复方案或与现有格式规则冲突之前,请按以下步骤操作:
- 检测代码仓库使用的linter:例如RuboCop(配置文件为,
.rubocop.yml中包含Gemfile依赖)、Standard Ruby(rubocop命令,standardrbgem)、前端linter(standard、eslint.config.*、.eslintrc*等),或是biome.json/package.json目录下的脚本(bin/、lint、rubocop)。standardrb - 运行项目文档中说明的、或是与配置匹配的lint命令,例如、
bundle exec rubocop、bundle exec standardrb。如果项目使用Standard或其他技术栈,请勿默认使用RuboCop。npm run lint
Quick Reference
快速参考
| Topic | Rule |
|---|---|
| Style/format | Project linter(s) — detect and run as above; do not invent style rules here |
| Principles | DRY, YAGNI, PORO where it helps, CoC, KISS |
| Comments | Explain why, not what; use tagged notes with context |
| Logging | First arg string, second arg hash; no string interpolation; |
| Deep stacks | Chain rails-stack-conventions → domain skills (services, jobs, RSpec) |
| 主题 | 规则 |
|---|---|
| 风格/格式 | 遵循项目linter规则,按上述步骤检测并执行;不要自行定义风格规则 |
| 设计原则 | DRY、YAGNI、适用场景下使用PORO、CoC、KISS |
| 注释 | 解释原因,而非内容;使用带上下文的标记注释 |
| 日志 | 第一个参数为字符串,第二个参数为哈希;不要使用字符串插值;便于看板查询时可添加 |
| 深层技术栈 | 优先参考rails-stack-conventions,再参考领域技能(服务、任务、RSpec) |
Design Principles
设计原则
| Principle | Apply as |
|---|---|
| DRY | Extract when duplication carries real maintenance cost; avoid premature abstraction |
| YAGNI | Build for current requirements; defer generalization until a second real use case |
| PORO | Use plain Ruby objects when they clarify responsibility; do not wrap everything in a "pattern" |
| Convention over Configuration | Prefer Rails defaults and file placement; document only intentional deviations |
| KISS | Simplest design that meets acceptance criteria and tests gate |
| 原则 | 适用方式 |
|---|---|
| DRY | 当重复代码确实会带来维护成本时再进行抽象;避免过早抽象 |
| YAGNI | 基于当前需求开发;直到出现第二个真实使用场景时再做通用化处理 |
| PORO | 当普通Ruby对象能明确职责时就使用它;不要把所有逻辑都套进某个「模式」里 |
| 约定优于配置 | 优先使用Rails默认配置和文件放置规则;仅对有意偏离约定的修改做文档说明 |
| KISS | 选择满足验收标准和测试门禁的最简单设计 |
Comments
注释规范
- Comment the why, not the what (the code shows what).
- Use tags with enough context that a future reader can act: ,
TODO:,FIXME:,HACK:,NOTE:.OPTIMIZE:
- 注释要说明为什么这么做,而非做了什么(代码本身已经能说明做了什么)。
- 使用带足够上下文的标记,方便后续维护者理解处理:、
TODO:、FIXME:、HACK:、NOTE:。OPTIMIZE:
Structured logging
结构化日志
- First argument: static string (message key or human-readable template without interpolated values).
- Second argument: hash with structured fields (,
user_id:, etc.).order_id: - Do not build the primary message with string interpolation; put dynamic data in the hash.
- Include (or equivalent) for error or ops dashboards when the team uses tagged events.
event:
- 第一个参数: 静态字符串(消息key或者不带插值的可读模板)。
- 第二个参数: 带结构化字段的哈希(例如、
user_id:等)。order_id: - 不要用字符串拼接生成主日志消息;把动态数据放到哈希参数里。
- 如果团队使用标记事件,可在错误或运维看板相关的日志中添加****(或等效字段)。
event:
Apply by area (path patterns)
分领域适用规则(路径匹配)
Rules below apply when those paths exist in the project. If a path is absent, skip that row.
| Area | Path pattern | Guidance |
|---|---|---|
| ActiveRecord performance | | Eager load in loops; push work into SQL where appropriate; prefer |
| Background jobs | | Clear worker/job structure, queue selection, idempotency, structured error logging (see rails-background-jobs for Active Job / Solid Queue / Sidekiq depth) |
| Error handling | | Domain exceptions with prefixed codes where the team uses them; |
| Logging / tracing | | Structured logging; add APM trace spans and tags (e.g. Datadog) for key operations when the stack includes them |
| Controllers | | Strong params; thin actions delegating to services; watch IDOR and PII exposure (see rails-security-review) |
| Repositories | | Avoid new repository objects unless raw SQL, caching, a clear domain boundary, or external service isolation justifies it; document why in code |
| RSpec | | FactoryBot; prefer request specs over controller specs; use |
| Serializers | | If using ActiveModel::Serializer (or similar): explicit |
| Service objects | | Single responsibility; class methods for stateless entry points, instance API when dependencies are injected; public methods first; bang ( |
| SQL security | Raw SQL anywhere | No string interpolation of user input; use |
以下规则仅当项目中存在对应路径时生效。如果路径不存在,可跳过对应规则。
| 领域 | 路径匹配 | 指导规则 |
|---|---|---|
| ActiveRecord 性能优化 | | 循环中使用预加载;合适的场景下把逻辑下沉到SQL执行;优先使用 |
| 后台任务 | | 清晰的worker/job结构、队列选择、幂等性、结构化错误日志(Active Job/Solid Queue/Sidekiq的深度规则请参考rails-background-jobs) |
| 错误处理 | | 团队有相关约定时使用带前缀编码的领域异常;按约定在API层使用 |
| 日志/链路追踪 | | 结构化日志;如果技术栈支持,为核心操作添加APM链路追踪span和标签(例如Datadog) |
| 控制器 | | 强参数校验;精简action逻辑,将业务逻辑委托给服务层;注意防范IDOR漏洞和PII泄露(请参考rails-security-review) |
| 仓库层 | | 除非有原生SQL、缓存、明确的领域边界、外部服务隔离等合理需求,否则不要新增仓库对象;在代码中注释说明新增仓库层的原因 |
| RSpec | | 使用FactoryBot;优先使用请求测试而非控制器测试;修改环境变量时使用 |
| 序列化器 | | 如果使用ActiveModel::Serializer(或同类工具):显式声明 |
| 服务对象 | | 单一职责;无状态入口使用类方法,需要注入依赖时使用实例API;公共方法放在前面;按规范使用感叹号( |
| SQL安全 | 任意位置的原生SQL | 不要对用户输入做字符串插值拼接SQL;使用 |
RSpec and let_it_be
(test-prof)
let_it_beRSpec与let_it_be
(test-prof)
let_it_be- Only use if the project already depends on the
let_it_begem (checktest-prof/Gemfile). Search before recommending it.Gemfile.lock - If is not present, follow rspec-best-practices with
test-profas the default; useletonly when lazy evaluation would break the example (e.g. callbacks, DB constraints that must exist before the action). Explicit setup is fine when clearer. Do not require addinglet!/test-profunless the user asks to introduce it.let_it_be
- 仅当项目已经依赖gem时才使用
test-prof(检查let_it_be/Gemfile),推荐使用前先搜索确认。Gemfile.lock - 如果未安装,遵循rspec-best-practices,默认使用**
test-prof**;仅当懒加载会破坏测试用例时才使用let(例如回调、执行操作前必须存在的数据库约束)。如果显式设置更清晰也可以直接使用。除非用户明确要求引入,否则不要推荐添加let!/test-prof依赖。let_it_be
HARD-GATE: Tests Gate Implementation
强制门禁:测试前置要求
When this skill guides new behavior, the tests gate still applies:
text
PRD → TASKS → TEST (write, run, fail) → IMPLEMENTATION → …No implementation code before a failing test. See rspec-best-practices and rails-agent-skills.
当本指南用于指导新功能开发时,仍然适用测试门禁规则:
text
PRD → TASKS → TEST (编写、运行、测试不通过) → IMPLEMENTATION → …在测试用例运行失败前不要编写实现代码。请参考rspec-best-practices和rails-agent-skills。
Common Mistakes
常见错误
| Mistake | Reality |
|---|---|
| Duplicate linter rules in prose | The project's configured linter(s) are authoritative for style; this skill is for behavior and boundaries |
| Assuming RuboCop without checking | Detect and run the linter the repo actually uses |
| Use only when |
Defaulting to | Prefer lazy |
New | ActiveRecord is the default data boundary unless there's a documented reason |
| Interpolated log messages | Loses structure; use hash payload |
| Comments restating method names | Adds noise; comment intent and tradeoffs |
| 错误做法 | 正确认知 |
|---|---|
| 在文档中重复定义linter规则 | 项目配置的linter是风格类规则的唯一权威依据;本指南仅用于行为和边界规范 |
| 不做检查就默认使用RuboCop | 检测并运行代码仓库实际使用的linter |
所有项目都用 | 仅当 |
所有场景都默认用 | 优先使用懒加载的 |
每个查询都新建 | ActiveRecord是默认的数据层边界,除非有明确的文档说明的理由 |
| 日志消息使用字符串插值 | 会丢失结构化特性;使用哈希传参承载动态数据 |
| 注释重复方法名内容 | 只会增加冗余;注释应该说明设计意图和取舍 |
Integration
关联指南
| Skill | When to chain |
|---|---|
| rails-stack-conventions | Stack-specific: PostgreSQL, Hotwire, Tailwind |
| ddd-rails-modeling | When domain concepts and invariants need clearer Rails-first modeling choices |
| ruby-service-objects | Implementing or refining service objects |
| rails-background-jobs | Workers, queues, retries, idempotency |
| rspec-best-practices | Spec style, tests gate (red/green/refactor), request vs controller specs |
| rails-security-review | Controllers, params, IDOR, PII |
| rails-code-review | Full PR pass before merge |
| 指南 | 适用场景 |
|---|---|
| rails-stack-conventions | 技术栈特定规则:PostgreSQL、Hotwire、Tailwind |
| ddd-rails-modeling | 需要基于Rails为领域概念和不变量做更清晰建模的场景 |
| ruby-service-objects | 实现或优化服务对象的场景 |
| rails-background-jobs | Workers、队列、重试、幂等性相关场景 |
| rspec-best-practices | 测试用例风格、测试门禁(红/绿/重构)、请求测试与控制器测试选择等场景 |
| rails-security-review | 控制器、参数、IDOR、PII相关安全检查场景 |
| rails-code-review | 合并前完整PR评审场景 |