ECC Ruby 编码风格实战指南:从 RuboCop 到 Rails 分层架构的规范落地
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
本指南以 ECC 仓库中 docs/ja-JP/rules/ruby/coding-style.md 为骨架,结合仓库内
rules/ruby/与rules/common/规则体系展开,面向在 Claude Code、Codex、OpenCode、Cursor 等 Agent 工作流中编写 Ruby / Rails 代码的开发者。读完本文,你将掌握 ECC 规则体系下 Ruby 3.3+ 与 YJIT 的取舍原则、RuboCop 与 binstub 的落地方式、Rails 分层职责边界、错误处理规范,以及如何通过 PostToolUse Hooks 和 CI 门槛把这些约定固化为自动化检查。
规则文件如何生效:路径匹配与分层继承
docs/ja-JP/rules/ruby/coding-style.md是 ECC 规则体系中 Ruby 语言分层的核心文件。其 frontmatter 定义了该规则自动激活的文件范围:
paths: - "**/*.rb" - "**/*.rake" - "**/Gemfile" - "**/*.gemspec" - "**/config.ru"也就是说,只要当前编辑或审查的对象是 Ruby 源码、Rake 任务、Gemfile、gemspec 或 Rack 配置文件,该规则就会被载入。
该文件开头明确声明它是对通用层规则 rules/common/coding-style.md 的 Ruby / Rails 专属扩展。ECC 采用"通用层 + 语言层"的分层规则架构(见 rules/README.md):rules/common/存放与语言无关的普适原则(不可变性、KISS/DRY/YAGNI、文件组织、错误处理、输入验证、命名规范、代码质量清单),语言目录(rules/ruby/、rules/python/、rules/golang/等)则以扩展声明的格式继承并细化。
关于优先级,rules/README.md 明确约定:当语言层规则与通用层规则冲突时,语言层规则优先(specific overrides general),类似于 CSS 特异性或.gitignore优先级规则。例如通用层推荐不可变模式,但个别语言惯用的可变写法可覆盖该默认值。Ruby 层同样遵循这一机制。
标准(Standards):运行时版本与性能取舍
目标 Ruby 3.3+
- 新 Rails 项目默认以Ruby 3.3+为目标运行时,除非项目已经固定了旧的受支持运行时。
- 这一约定与 rules/ruby/testing.md、rules/ruby/patterns.md 中"以 Rails 8 为默认栈"的前提保持一致(Rails 8 要求较新的 Ruby 运行时,而 3.3+ 提供更成熟的性能与内存表现)。
YJIT 必须基于实测启用
- YJIT只在生产环境实测启动时间、内存占用、请求/Job 吞吐量之后才启用,禁止不加测量地"顺手打开"。
- 理由是 YJIT 通过把 Ruby 字节码编译为机器码换取执行速度,但会以额外内存占用为代价,不同负载模型下收益差异显著。正确的做法是:先在 staging 或灰度环境跑基准,比较启用前后的三项指标,再决定是否在启动参数层(如
RUBYOPT=--yjit)或初始化配置中开启。
frozen_string_literal 约定
- 当项目采用
# frozen_string_literal: true约定时,新 Ruby 文件必须加上该魔法注释。它把字符串字面量标记为不可变,避免意外修改共享字符串,同时减少字符串对象分配,与 rules/common/coding-style.md 中"不可变性(CRITICAL)"的通用原则一脉相承——通用层要求"永远创建新对象、绝不原地修改既有对象",Ruby 的冻结字面量正是该原则在语言层面的落点。
明快的 Ruby 优于炫技的元编程
- 优先书写清晰的 Ruby,而非精巧的元编程;重度 DSL 代码必须隔离在窄小、有测试覆盖的边界之后。
- 元编程(
define_method、method_missing、class_eval等)会把运行时行为藏起来,破坏静态可读性与 IDE/Agent 的符号解析能力。如果确实需要,应封装成独立模块并配齐单元测试,让黑魔法的影响面可控。
格式与 Lint(Formatting and Linting):RuboCop 落地
配置来源与默认起点
- 使用项目已签入仓库的 RuboCop 配置(
.rubocop.yml),保证团队与 CI 使用同一套规则。 - Rails 8+ 应用从
rubocop-rails-omakase起步——这是 Rails 官方维护的默认风格包,开箱即用、约定合理;只有代码库存在真实惯例时,才在其上自定义规则,避免早期就陷入规则争论。
命令必须走 binstub 或脚本
格式化/Lint 命令放在 binstub 或脚本之后,确保 CI 与本地执行完全一致。原文档给出的核心命令:
bundle exec rubocop bundle exec rubocop -Abundle exec rubocop:只报告问题,不修改文件,适合 CI 门禁。bundle exec rubocop -A:自动修正(autocorrect)可安全修复的违规项,适合本地提交前跑一遍。
内联禁用 cop 的纪律
- 不内联禁用 cop(如
# rubocop:disable ...),除非该异常是窄小的、有文档说明的,并且很难在代码中干净地表达。 - 与其到处打 disable 补丁,不如在配置层面针对全仓库做有据可查的调整,或重构代码本身以符合规范。
Rails 风格(Rails Style):分层职责与目录约定
先遵循约定,再谈自定义
- 在引入自定义结构之前,先遵循 Rails 的命名约定与目录约定(
app/models、app/controllers、app/views、config/routes.rb等)。这一点与 rules/ruby/patterns.md 的 "Rails Way First" 原则一致:中小型功能先用朴素 Rails MVC + Active Record 惯例,当模型/控制器边界开始承担多重职责时,才引入 service object、query object、form object、decorator 或 presenter。
控制器只做传输层的事
控制器的关注点严格限定在四件事:
- 认证(authentication):确认"你是谁"
- 授权(authorization):确认"你能不能做"
- 参数处理(parameter handling):使用 strong parameters 白名单收参
- 响应形状(response shape):决定返回 JSON / HTML / redirect 及状态码
业务逻辑不得泄漏进控制器。可复用的领域行为按实际复杂度放置于模型、concerns、service objects、query objects 或 form objects,而不是当作默认仪式到处建目录——复杂度低就放模型,复杂度高了再提取,这正好呼应 rules/common/coding-style.md 的 YAGNI 原则:"当压力真实存在时才抽象,而非投机式泛化"。
从源码结构看,ECC 仓库在 skills/backend-patterns/SKILL.md 中给出了服务层 / 仓库层 / 中间件模式的通用实现参考,并指出"选择与你的复杂度匹配的模式"——Ruby 层的控制器-模型二分法与之一致:先薄,后分层。
优先 binstub 而非全局命令
- 优先
bin/rails、bin/rake及签入仓库的 binstub,而非全局安装的命令。 - 原因是 binstub 绑定项目自身的 gem 版本与加载路径,杜绝"本机能跑、CI 挂了"的版本漂移问题。
bin/rails同时支持rails的全部子命令(server、generate、db:migrate等)。
错误处理(Error Handling):精确 rescue 与可观测日志
rescue 特定异常,避免大网兜底
- 只 rescue 你能处理的具体异常。
- 避免宽泛的
rescue StandardError块,除非:块内重新抛出(re-raise),或者为运维人员保留足够的上下文(异常对象、请求 ID、参数快照等)。 - 静默吞掉异常是 rules/common/coding-style.md 明确禁止的行为:"绝不静默吞掉错误"——错误要么被显式处理,要么被带上上下文重新抛出。
用 Notifications 或 Logger,别留调试器
- 运维事件使用
ActiveSupport::Notifications(Rails 内置的发布/订阅观测点,适合做指标、审计、跨请求追踪)或应用自身的 logger。 - 已提交的应用代码中不得遗留
puts、pp、debugger。这条约束在 rules/ruby/hooks.md 中被进一步固化为 PostToolUse Hooks 警告:编辑后若检测到提交代码中出现debugger、binding.irb、binding.pry、puts、pp、p调用,立即向开发者告警。
配套规则协同:测试、安全与 Hooks 门禁
编码风格不是孤立的,ECC 的 Ruby 规则包(rules/ruby/目录)以 coding-style.md 为纲,配套五份文件共同构成完整的质量闭环:
| 文件 | 主题 | 关键约束 |
|---|---|---|
| rules/ruby/coding-style.md | 编码风格 | 版本、YJIT、RuboCop、分层、错误处理 |
| rules/ruby/patterns.md | 架构模式 | Rails Way First、PostgreSQL、Solid Queue/Sidekiq、Hotwire、认证选型 |
| rules/ruby/testing.md | 测试 | Minitest/RSpec 二选一、测试金字塔、fixtures/factory_bot |
| rules/ruby/security.md | 安全 | CSRF、strong parameters、参数化 SQL、bundle-audit/brakeman |
| rules/ruby/hooks.md | Agent Hooks | PostToolUse 自动格式化、安全扫描、测试与警告 |
测试侧协同(rules/ruby/testing.md)
- 框架二选一:默认 Rails 测试栈用 Minitest;项目已确立 RSpec 惯例时用 RSpec,同一功能区内不混用。
- 命令也走项目本地 binstub:
bin/rails test bin/rails test test/models/user_test.rb bundle exec rspec bundle exec rspec spec/models/user_spec.rb- 覆盖率用 SimpleCov 并在 CI 中设定阈值,避免用低价值测试刷分支覆盖率;bug 修复先补回归测试再改生产代码。
安全侧协同(rules/ruby/security.md)
- 状态变更请求保持 CSRF 防护开启;批量赋值前用 strong parameters 或类型化边界对象。
- 密钥存于 Rails credentials、环境变量或密钥管理服务,绝不提交明文 key、token 或复制
.env值。 - SQL 一律走 Active Record 查询 API 与参数化语句,绝不把请求、Cookie、Header、Job 或 Webhook 值插值进 SQL 字符串。
- 依赖变更时运行:
bundle exec bundle-audit check --update bundle exec brakeman --no-progressbundle-audit扫描已知漏洞依赖,brakeman做 Rails 静态安全分析。两者同样出现在 rules/ruby/hooks.md 的 CI 门禁建议中。
Agent Hooks 侧协同(rules/ruby/hooks.md)
rules/ruby/hooks.md把编码风格固化为 Agent 工作流中的自动化检查点:
- RuboCop:Ruby 编辑后运行
bundle exec rubocop -A <file>或项目更安全的格式化命令; - Brakeman:安全敏感的 Rails 变更后运行
bundle exec brakeman --no-progress; - 测试:对触及的文件运行最窄匹配的
bin/rails test ...或bundle exec rspec ...; - Bundler audit:
Gemfile/Gemfile.lock变更且项目装有 bundler-audit 时运行bundle exec bundle-audit check --update。
同时设置三类警告:提交了调试代码;编辑禁用了 CSRF、扩大了批量赋值或加入未参数化 SQL;迁移以破坏性方式改数据却没有可回滚路径或上线方案。推荐的 CI 门槛组合为:
bundle exec rubocop bundle exec brakeman --no-progress bin/rails test bundle exec rspec仅使用项目实际存在的命令,未经维护者批准不安装新的 Hook 依赖。
落地检查清单
将编码风格规则与 rules/common/coding-style.md 的质量清单结合,完成 Ruby 工作时逐项核对:
- 新 Rails 项目目标运行时为 Ruby 3.3+;YJIT 仅在实测启动/内存/吞吐后启用
- 新 Ruby 文件按项目约定带
# frozen_string_literal: true - 元编程与 DSL 隔离在窄小且有测试覆盖的边界内
bundle exec rubocop与bundle exec rubocop -A走 binstub,CI 与本地一致- 控制器只做认证/授权/参数/响应形状,领域逻辑按复杂度下沉到模型或服务层
- 优先
bin/rails、bin/rake,避免全局命令 - rescue 具体异常;宽泛 rescue 要么重抛、要么保留运维上下文
- 使用
ActiveSupport::Notifications或 logger,无puts/pp/debugger残留 - 依赖变更后运行
bundle-audit与brakeman;安全敏感变更走 Hooks 门禁
参考延伸
- 规则体系的通用层基座:rules/common/coding-style.md
- Ruby 规则包全貌:rules/ruby/(coding-style、patterns、testing、security、hooks 五份文件)
- 服务 / 仓库分层与适配器模式的纵深参考:技能 skills/backend-patterns/SKILL.md(文档"参考"节明确指向该技能)
- 规则的分层架构、安装方式与优先级说明:rules/README.md
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考