Attention
Unlike RuboCop, not every code smell warrants action. I recommend using Reek primarily as a tool to help gauge the quality of a merge request or for feedback for your AI agent, not to block a PR from getting merged. Code without any reek warning might not be better than code with warnings.
Reek is a linter for detecting code smells and antipatterns in your Ruby codebase. It works similarly to RuboCop but focuses more on high-level issues. Unlike RuboCop, there is no "autofix" for these smells; each of them needs to be assessed on a case-by-case basis.
Integrating Reek in an existing project
Add:
gem "reek", group: [:test, :development]
To run Reek on your Rails project:
$ bundle exec reek app lib config test
This will check the existing code for antipatterns in a few seconds. An average project will likely produce thousands of warnings.
For an initial starting point, you can generate and commit a .reek.yml file that ignores all existing violations while flagging newly introduced ones:
$ bundle exec reek --todo
Example output for the " Long Parameter List Show archive.org snapshot " smell:
app/models/foo.rb -- 1 warning:
[1]:LongParameterList: Foo#bar has 5 parameters [https://github.com/troessner/reek/blob/v6.5.0/docs/Long-Parameter-List.md]
Opiniated default
IrresponsibleModule forces a comment above all classes / modules.
IrresponsibleModule:
enabled: false
Gitlab CI integration
To avoid failing your PR, consider the following configuration:
reek:
stage: lint
script:
- bundle exec reek app lib config test
allow_failure: true # a reek failure will only create a "warning" and not block a merge
Agent integration
Consider adding adapting your AGENTS.md as well:
We integrate the Reek code smell detector as a Ruby linter.
Call it with `bundle exec reek` on your changed files. It also runs as a `reek` job on CI.
A reek warning is a signal for a potential code issue, not a blocker. Only address the warnings you agree with.
When you disagree with a warning, [suppress it with a comment](https://github.com/troessner/reek/blob/master/docs/Smell-Suppression.md).
A suppression comment should include both the smell identifier and the reason for suppression, in prose. For example:
# This method smells of :reek:FeatureEnvy, but we intentionally
# want to keep price calculations out of the Item class.
def smelly_method
def sale_price(item)
(item.price - item.rebate) * @vat
end
end