visit
Rubocop is a code-style linter for Ruby based on the official
Creating a Standard: There are various patterns in which developers write code. To harmonize the coding style, we can use Rubocop. By enabling and disabling rules with Rubocop, we can discuss with the team what good practices we need to follow.
Ease the process of understanding & reviewing code: Sometimes, when a PR is sent for review, the reviewer might spend time commenting on the code style/format, such as extra whitespaces and missing lines at the end. By integrating Rubocop into pre-commit hooks and GitHub Actions, the developer can be made aware of offenses even before the PR is reviewed.
Best Practices: As Ruby beginners, we may not be aware of the practices used by the Ruby community. In the form of various gems, Rubocop provides us with an excellent starting point for understanding all of them.
gem 'rubocop', '1.23.0', require: false
gem 'rubocop-performance', '~> 1.12.0', require: false
gem 'rubocop-rails', '~> 2.12.0', require: false
gem 'rubocop-rake', '~> 0.6.0', require: false
gem 'rubocop-rspec', '~> 2.6.0', require: false
The next step is to create the .rubocop.yml
which contains the cops to be enabled/disabled, and the files that we don't want to run specific cops on.
require:
- rubocop-performance
- rubocop-rake
- rubocop-rails
- rubocop-rspec
AllCops:
DisabledByDefault: false
NewCops: enable
TargetRubyVersion: 2.6.3
Exclude:
- db/schema.rb
- node_modules/**/*
- vendor/**/*
Layout/FirstArgumentIndentation:
Exclude:
- spec/controllers/api/payments_controller_spec.rb
disables running of Cop Layout/FirstArgumentIndentation
on the files under Exclude.
For existing projects, RuboCop provides a file .rubocop_todo.yml
that records all the offenses from our codebase. Rather than having to fix everything at once, we can fix each offense as we touch the corresponding piece of code.
In order to generate the todo file use the command rubocop --auto-gen-config --exclude-limit 10000
which runs rubocop on your entire codebase and adds the offenses in the code as disabled.
--exclude-limit 10000
is a hack to make sure that Rubocop will not disable any cops in the .rubocop_todo.yml file
.
An example of how the .rubocop_todo.yml
will look like
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 10000`
# on 2022-09-24 07:33:55 UTC using RuboCop version 1.23.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: IndentationWidth.
Layout/AssignmentIndentation:
Exclude:
- 'app/controllers/home_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/regex_helper.rb'
The next step is to let rubocop
know to ignore the files in .rubocop_todo.yml
. You can do this by inheriting the file in the main config.
inherit_from: .rubocop_todo.yml
inherit_mode:
merge:
- Exclude
require:
- rubocop-performance
- rubocop-rake
- rubocop-rails
- rubocop-rspec
...
This is how your .rubocop.yml
will look after configuring the todo file. Then when we run rubocop, it pulls the configuration from .rubocop.yml
, which then pulls the configuration from .rubocop_todo.yml
, which contains all the excluded files. Therefore, we won't see any offenses.
The approach that we have been following at HackerRank to solve these offenses includes the following steps:
Pick up a cop with offenses in the .rubocop-todo.yml
file.
Read the documentation at
Check if the Cop supports Safe Autocorrection.
As I was cleaning up the .rubocop-todo.yml
file at HackerRank, we discovered that some cops needed configs different from what the official Ruby style guide recommends. Listed below are a few examples of those, along with the reason and how you can modify the defaults.
You can disable this cop using the following piece of code in .rubocop.yml
Style/RedundantReturn:
Enabled: false
%
format for strings that don't have any spaces. In the case of spaces using the %w
will be considered an offense.
# bad
STATES = ['draft', 'open', 'closed']
# good
STATES = %w[draft open closed]
# bad (contains spaces)
STR = %w[foo\ bar baz\ quux]
# good (contains spaces)
STR = ['foo bar', 'baz quux']
For the above two reasons, we configured the default to Brackets
. You can use the following piece in .rubocop.yml
.
Style/WordArray:
EnforcedStyle: brackets
Style/WordArray
.
Style/SymbolArray:
EnforcedStyle: brackets
It also provides a configuration like CountAsOne which is available for array, hash, and heredoc where each literal will be counted as one line regardless of its actual size & IgnoredMethods where we can provide the list of methods that we want the cop to ignore.
Metrics/MethodLength:
Max: 100
CountAsOne: ['array', 'hash', 'heredoc']
IgnoredMethods: ['a','b']
Make use of pre-commit hooks that run Rubocop across all the configured Cops.
Setup Code Climate/Github Actions that report offenses on the PR. You can also make these checks as required to pass for merging the code.
PS: The following screenshot is a trend on how we have improved the code quality atHackerRank by cleaning up the .rubocop_todo.yml
file.
I hope this article helps to configure Rubocop in your code bases & improve the code quality.