rails-principles-and-boundaries

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rails 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:
  1. Detect which linter(s) the repo uses — e.g. RuboCop (
    .rubocop.yml
    ,
    rubocop
    in
    Gemfile
    ), Standard Ruby (
    standardrb
    ,
    standard
    gem), frontend linters (
    eslint.config.*
    ,
    .eslintrc*
    ,
    biome.json
    , etc.), or scripts in
    package.json
    /
    bin/
    (
    lint
    ,
    rubocop
    ,
    standardrb
    ).
  2. Run the command the project documents or that matches the config (e.g.
    bundle exec rubocop
    ,
    bundle exec standardrb
    ,
    npm run lint
    ). Do not assume RuboCop if the project uses Standard or another stack.
在推荐风格修复方案或与现有格式规则冲突之前,请按以下步骤操作:
  1. 检测代码仓库使用的linter:例如RuboCop(配置文件为
    .rubocop.yml
    Gemfile
    中包含
    rubocop
    依赖)、Standard Ruby(
    standardrb
    命令,
    standard
    gem)、前端linter(
    eslint.config.*
    .eslintrc*
    biome.json
    等),或是
    package.json
    /
    bin/
    目录下的脚本(
    lint
    rubocop
    standardrb
    )。
  2. 运行项目文档中说明的、或是与配置匹配的lint命令,例如
    bundle exec rubocop
    bundle exec standardrb
    npm run lint
    。如果项目使用Standard或其他技术栈,请勿默认使用RuboCop。

Quick Reference

快速参考

TopicRule
Style/formatProject linter(s) — detect and run as above; do not invent style rules here
PrinciplesDRY, YAGNI, PORO where it helps, CoC, KISS
CommentsExplain why, not what; use tagged notes with context
LoggingFirst arg string, second arg hash; no string interpolation;
event:
when useful for dashboards
Deep stacksChain rails-stack-conventions → domain skills (services, jobs, RSpec)
主题规则
风格/格式遵循项目linter规则,按上述步骤检测并执行;不要自行定义风格规则
设计原则DRY、YAGNI、适用场景下使用PORO、CoC、KISS
注释解释原因,而非内容;使用带上下文的标记注释
日志第一个参数为字符串,第二个参数为哈希;不要使用字符串插值;便于看板查询时可添加
event:
字段
深层技术栈优先参考rails-stack-conventions,再参考领域技能(服务、任务、RSpec)

Design Principles

设计原则

PrincipleApply as
DRYExtract when duplication carries real maintenance cost; avoid premature abstraction
YAGNIBuild for current requirements; defer generalization until a second real use case
POROUse plain Ruby objects when they clarify responsibility; do not wrap everything in a "pattern"
Convention over ConfigurationPrefer Rails defaults and file placement; document only intentional deviations
KISSSimplest 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:
    ,
    order_id:
    , etc.).
  • Do not build the primary message with string interpolation; put dynamic data in the hash.
  • Include
    event:
    (or equivalent) for error or ops dashboards when the team uses tagged events.
  • 第一个参数: 静态字符串(消息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.
AreaPath patternGuidance
ActiveRecord performance
app/models/**/*.rb
Eager load in loops; push work into SQL where appropriate; prefer
pluck
,
exists?
,
find_each
over loading full records unnecessarily
Background jobs
app/workers/**/*.rb
,
app/jobs/**/*.rb
Clear worker/job structure, queue selection, idempotency, structured error logging (see rails-background-jobs for Active Job / Solid Queue / Sidekiq depth)
Error handling
app/services/**/*.rb
,
app/lib/**/*.rb
,
app/exceptions/**/*.rb
Domain exceptions with prefixed codes where the team uses them;
rescue_from
or base handlers for API layers as conventions dictate
Logging / tracing
app/services/**/*.rb
,
app/workers/**/*.rb
,
app/jobs/**/*.rb
,
app/controllers/**/*.rb
,
app/repositories/**/*.rb
Structured logging; add APM trace spans and tags (e.g. Datadog) for key operations when the stack includes them
Controllers
app/controllers/**/*_controller.rb
Strong params; thin actions delegating to services; watch IDOR and PII exposure (see rails-security-review)
Repositories
app/repositories/**/*.rb
Avoid new repository objects unless raw SQL, caching, a clear domain boundary, or external service isolation justifies it; document why in code
RSpec
spec/**/*_spec.rb
FactoryBot; prefer request specs over controller specs; use
env:
metadata (or project equivalent) for ENV changes; prefer
let
over
let!
unless the example requires eager setup; avoid
before
for data when
let
or inline factories are clearer
Serializers
app/serializers/**/*.rb
If using ActiveModel::Serializer (or similar): explicit
key:
mapping; avoid N+1; pass preloaded associations via options when applicable
Service objects
app/services/**/*.rb
Single responsibility; class methods for stateless entry points, instance API when dependencies are injected; public methods first; bang (
!
) / predicate (
?
) naming as appropriate (see ruby-service-objects)
SQL securityRaw SQL anywhereNo string interpolation of user input; use
sanitize_sql_array
/ bound parameters; whitelist dynamic ORDER BY; document why raw SQL is needed
以下规则仅当项目中存在对应路径时生效。如果路径不存在,可跳过对应规则。
领域路径匹配指导规则
ActiveRecord 性能优化
app/models/**/*.rb
循环中使用预加载;合适的场景下把逻辑下沉到SQL执行;优先使用
pluck
exists?
find_each
,避免不必要的全量记录加载
后台任务
app/workers/**/*.rb
,
app/jobs/**/*.rb
清晰的worker/job结构、队列选择、幂等性、结构化错误日志(Active Job/Solid Queue/Sidekiq的深度规则请参考rails-background-jobs
错误处理
app/services/**/*.rb
,
app/lib/**/*.rb
,
app/exceptions/**/*.rb
团队有相关约定时使用带前缀编码的领域异常;按约定在API层使用
rescue_from
或基础异常处理器
日志/链路追踪
app/services/**/*.rb
,
app/workers/**/*.rb
,
app/jobs/**/*.rb
,
app/controllers/**/*.rb
,
app/repositories/**/*.rb
结构化日志;如果技术栈支持,为核心操作添加APM链路追踪span和标签(例如Datadog)
控制器
app/controllers/**/*_controller.rb
强参数校验;精简action逻辑,将业务逻辑委托给服务层;注意防范IDOR漏洞和PII泄露(请参考rails-security-review
仓库层
app/repositories/**/*.rb
除非有原生SQL、缓存、明确的领域边界、外部服务隔离等合理需求,否则不要新增仓库对象;在代码中注释说明新增仓库层的原因
RSpec
spec/**/*_spec.rb
使用FactoryBot;优先使用请求测试而非控制器测试;修改环境变量时使用
env:
元数据(或项目等效写法);优先使用
let
而非
let!
,除非测试用例需要提前加载;当
let
或内联factory写法更清晰时,不要用
before
做数据准备
序列化器
app/serializers/**/*.rb
如果使用ActiveModel::Serializer(或同类工具):显式声明
key:
映射;避免N+1查询;适用场景下通过参数传入预加载的关联数据
服务对象
app/services/**/*.rb
单一职责;无状态入口使用类方法,需要注入依赖时使用实例API;公共方法放在前面;按规范使用感叹号(
!
)/谓词(
?
)命名(请参考ruby-service-objects
SQL安全任意位置的原生SQL不要对用户输入做字符串插值拼接SQL;使用
sanitize_sql_array
/参数绑定;动态ORDER BY场景使用白名单;注释说明使用原生SQL的原因

RSpec and
let_it_be
(test-prof)

RSpec与
let_it_be
(test-prof)

  • Only use
    let_it_be
    if the project already depends on the
    test-prof
    gem
    (check
    Gemfile
    /
    Gemfile.lock
    ). Search before recommending it.
  • If
    test-prof
    is not present
    , follow rspec-best-practices with
    let
    as the default
    ; use
    let!
    only 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 adding
    test-prof
    /
    let_it_be
    unless the user asks to introduce it.
  • 仅当项目已经依赖
    test-prof
    gem时才使用
    let_it_be
    (检查
    Gemfile
    /
    Gemfile.lock
    ),推荐使用前先搜索确认。
  • 如果未安装
    test-prof
    ,遵循rspec-best-practices,默认使用**
    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-practicesrails-agent-skills

Common Mistakes

常见错误

MistakeReality
Duplicate linter rules in proseThe project's configured linter(s) are authoritative for style; this skill is for behavior and boundaries
Assuming RuboCop without checkingDetect and run the linter the repo actually uses
let_it_be
in every project
Use only when
test-prof
is already a dependency
Defaulting to
let!
everywhere
Prefer lazy
let
; reserve
let!
for cases that need eager setup
New
app/repositories
for every query
ActiveRecord is the default data boundary unless there's a documented reason
Interpolated log messagesLoses structure; use hash payload
Comments restating method namesAdds noise; comment intent and tradeoffs
错误做法正确认知
在文档中重复定义linter规则项目配置的linter是风格类规则的唯一权威依据;本指南仅用于行为和边界规范
不做检查就默认使用RuboCop检测并运行代码仓库实际使用的linter
所有项目都用
let_it_be
仅当
test-prof
已经是项目依赖时才使用
所有场景都默认用
let!
优先使用懒加载的
let
;仅在需要提前加载的场景使用
let!
每个查询都新建
app/repositories
ActiveRecord是默认的数据层边界,除非有明确的文档说明的理由
日志消息使用字符串插值会丢失结构化特性;使用哈希传参承载动态数据
注释重复方法名内容只会增加冗余;注释应该说明设计意图和取舍

Integration

关联指南

SkillWhen to chain
rails-stack-conventionsStack-specific: PostgreSQL, Hotwire, Tailwind
ddd-rails-modelingWhen domain concepts and invariants need clearer Rails-first modeling choices
ruby-service-objectsImplementing or refining service objects
rails-background-jobsWorkers, queues, retries, idempotency
rspec-best-practicesSpec style, tests gate (red/green/refactor), request vs controller specs
rails-security-reviewControllers, params, IDOR, PII
rails-code-reviewFull PR pass before merge
指南适用场景
rails-stack-conventions技术栈特定规则:PostgreSQL、Hotwire、Tailwind
ddd-rails-modeling需要基于Rails为领域概念和不变量做更清晰建模的场景
ruby-service-objects实现或优化服务对象的场景
rails-background-jobsWorkers、队列、重试、幂等性相关场景
rspec-best-practices测试用例风格、测试门禁(红/绿/重构)、请求测试与控制器测试选择等场景
rails-security-review控制器、参数、IDOR、PII相关安全检查场景
rails-code-review合并前完整PR评审场景