ruby代码分析
在Memory.ai,我们开始大量使用RuboCop。 这是关于我们如何将RuboCop集成到现有应用程序中的故事。
这不是RuboCop的介绍性帖子。 在深入了解我们的体验报告之前,请先查看RuboCop是什么。
我们从rubocop
, rubocop-performance
, rubocop-rails
和rubocop-rspec
宝石开始。 默认情况下,我们启用了所有警察,这是我们在rubocop.yml.
的初始配置rubocop.yml.
require:
- rubocop-rspec
- rubocop-rails
- rubocop-performance
AllCops:
EnabledByDefault: true
TargetRubyVersion: 2.6 . 3
Exclude:
- 'app/views/**/*'
- 'db/**/*'
- 'bin/**/*'
- 'csv/**/*'
- 'slate/**/*'
- 'vendor/bundle/**/*'
- 'node_modules/**/*'
如果在现有项目中启用了RuboCop随附的所有警察,则将收到无数警告和冒犯。 在添加以上配置后运行rubocop
时,这一点非常明显。
对于现有项目,有一种更好的方式集成RuboCop。 RuboCop提供了一个.rubocop_todo.yml
文件,该文件记录了我们代码库中的所有违规行为。 当我们触摸特定代码段时,我们可以一一解决这些违规行为。 因此,我们不必先解决所有问题。
要开始使用.rubocop_todo.yml
,请执行以下步骤。
bundle exec rubocop --auto-gen-config
Added inheritance from`.rubocop_todo.yml` in `.rubocop.yml` .
Phase 1 of 2 : run Metrics/LineLength cop
Inspecting 38 files
CC....C..C..C...C..CCC..CC....CC..C..C
38 files inspected, 40 offenses detected
Created .rubocop_todo.yml.
Phase 2 of 2 : run all cops
Inspecting 38 files
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
38 files inspected, 104 offenses detected
Created .rubocop_todo.yml.
您将看到类似的输出,但是根据代码库的状态,攻击的数量可能极大,也可能非常少:)
这个命令做了三件事。
让我们看看.rubocop_todo.yml
的内容 。 它记录了我们代码中存在的所有违法行为。 让我们看一下其中一位警察的示例,以更好地理解。
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: TreatCommentsAsGroupSeparators, Include.
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
Bundler/OrderedGems:
Exclude:
- 'Gemfile'
这Bundler/OrderedGems
代码告诉我们,我们的代码库对Bundler/OrderedGems
cop有一个冒犯,我们该如何解决。 但更重要的是,它会将存在该攻击的文件标记为将从中运行RuboCop的文件列表中排除 。
这是什么意思? 好吧,让我们现在尝试在整个项目上运行rubocop。
▶ bundleexec rubocop
Inspecting 38 files
......................................
38 files inspected, no offenses detected
哇! 我们的代码是干净的,它通过了所有警察,可以参加聚会了!
好吧,不是真的。 这是需要查看注释从.rubocop_todo.yml继承的.rubocop.yml的地方 。
▶ cat .rubocop.yml
inherit_from: .rubocop_todo.yml
.rubocop_todo.yml
记录了我们代码库的所有违规行为,并且还从将运行rubocop的列表中排除了这些文件。
.rubocop.yml
继承自.rubocop_todo.yml
因此它也从将运行rubocop的列表中排除了那些文件。
当我们运行bundle exec rubocop
,从拿起配置.rubocop.yml
这反过来又拾起从配置.rubocop_todo.yml
已经排除了所有具有罪行的文件。 所有这些结果从bundle exec rubocop
命令变为绿色输出。
因此,我们仍然拥有RuboCop不喜欢的令人讨厌的代码,但是我们有一种策略来逐步修复它,而不是一次全部修复它。
专家提示:将Rubocop集成到现有项目时,请始终生成.rubocop_todo.yml。
下一步自然是对.rubocop_todo.yml
文件采取行动,并在我们触及现有的攻击性代码并确保我们编写的新代码紧随警察之后,修复攻击。
我们决定添加一个git钩子,该钩子将在分阶段的更改上运行RuboCop。 RuboCop提供了--safe-autocorrect
选项,该选项--safe-autocorrect
根据特定警察是否被认为可以自动更正来自动更正某些代码。 我们在git commit钩子中利用了这一点,以便开发人员不必担心手动修复所有问题。 当机器可以做到时,为什么不呢?
我们用husky
和lint-staged
NPM包来实现这一目标。
npm install --save-dev lint-staged husky
在package.json
添加以下内容
{"scripts" : {
"precommit" : "lint-staged"
},
"lint-staged" : {
{app,spec}/**/*.rb ": [
" bundle exec rubocop --safe-autocorrect ",
" git add "
]
},
" devDependencies ": {
" husky ": " ^ 0.13 .4 ",
" lint-staged ": " ^ 3.6 .0 "
}
}
这种配置确保了每当开发人员尝试提交代码时,RuboCop认为该代码中的安全漏洞以及支持“ 自动更正”机制的警察都已得到修复。 此后,我们的开发人员无需做任何其他事情,除了修复RuboCop认为不安全的违法行为。
一旦自动更正git钩子开始起作用,我们的攻击清单就会开始下降。 我们必须在两者之间重新生成.rubocop_todo.yml才能获得准确的犯罪清单。 我们决定不将.rubocop_todo.yml的再生添加到Git挂钩中,因为在我们的情况下这很慢。
.rubocop_todo.yml可以从生成它的同一命令中重新生成。
毕竟,我们希望攻击性代码会下降,并且代码质量会每天提高,而不会出现任何错误。 但是我们面临的挑战很少。
自动更正钩子在此过程中对我们的代码进行了一些意外更改。
我们有一段代码,其中包含方法update_attributes。 rubocop-rails
gem有一个cop ActiveRecord/Aliases
rubocop-rails
,可以通过update更改对update_attributes的调用。 尽管此更改仅应在Active Record模型上发生,但cop不会检查是否在Active Record模型上调用了该方法。
因此,在我们的案例中,它将对update_attributes的调用更改为update,但未更改方法定义。 它仍然是update_attributes。 这导致了错误。 由于我们启用了安全自动校正Git钩子,因此开发人员只有在CI中的构建失败时才知道这一点。
我们还遇到了其他一些警察的问题,例如Rails / SaveBang和Style/StringHashKeys
,他们更改了原本应该Style/StringHashKeys
的代码。
最后,我们决定删除安全的自动更正钩子,并依靠手动固定攻击性代码。
当我们遇到与某些警察相关的问题,这些问题对于安全自动更正选项而言并不十分安全时,我们尝试通过将补丁提交给RuboCop来修复它们。
我会鼓励每个人都这样做,因为它使RuboCop对每个人都更好。
最后,我将列出从这次采用中学到的知识。
增量采用是关键。
自动更正可能会很棘手,具体取决于您的测试覆盖率和许多其他因素,因此如果不需要,请不要使用它。
禁用您的团队不同意的警察。 我们禁用了警察,例如RSpec/AnyInstance
, RSpec/ExpectInHook,
RSpec/AlignRightLetBrace
通过您的发现和代码修复为社区做出贡献 ,从而使RuboCop等关键工具对每个人都变得更好。
想知道我们如何做Ruby和Rails在Memory.ai,订阅我的通讯 这里 。
您使用RuboCop吗? 让我知道下面的评论或Twitter上的评论 @ _cha1tanya
翻译自: https://hackernoon.com/making-friends-with-rubocop-ruby-static-code-analyzer-rp9c36wr
ruby代码分析