The longer I have been in programming, the more I think that following best practices for coding style is an essential quality of a good programmer. When working on a team, I find many people want to debate about these things. While this can be fun, after a while it can become a time suck and a waste of energy. The best thing is to simply agree on a standard style guide and conform to it.
In April 2014, I was introduced to Rubocop. Similar to JSLint, Rubocop follows a standard Ruby style guide and includes a command line program for checking for clear violations. It has a clearly defined style guide that is customizable via a yaml file. What follows is how I use it in my current Ruby on Rails projects.
Getting started
After following the Rubocop gem installation instructions, checking for violations is simple:
$ rubocop
If it is an existing project, there will be tons of violations. This should not overwhelm because Rubocop has a nice way of letting me gradually fix violations. By creating the .rubocop_todo.yml
file, I see the work that needs to be done. To do this:
$ rubocop --auto-gen-config
Next, I create a the .rubocop.yml
file. My standard .rubocop.yml
file looks like this. It inherits from the .rubocop_todo.yml
. It excludes files that are generated by Rails itself. It also includes some of my opinions about what is acceptable violations. For example, I don’t find empty lines around modules and blocks to be violations.
inherit_from: .rubocop_todo.yml
AllCops:
Exclude:
- db/schema.rb
- db/migrate/*
- bin/*
RunRailsCops: true
Documentation:
Enabled: false
DotPosition:
EnforcedStyle: trailing
Style/EmptyLinesAroundBlockBody:
Enabled: false
Style/EmptyLinesAroundModuleBody:
Enabled: false
Style/EmptyLinesAroundClassBody:
Enabled: false
Style/EmptyLinesAroundMethodBody:
Enabled: false
Now, I should have a clean run when I do:
$ rubocop
Next, I add a task that runs on the continuous integration server to make sure this is enforced. I create a file lib/tasks/ci.rake
and add two rake tasks: ci:rubocop
and ci:rubocop_changed
. One will run on CI and the other will run as part of my ‘git’ pre-commit hook. The tasks looks like this:
On my continuous integration server, I will add bundle exec rake ci:rubocop
as step in the build.
Locally, I change my .git/hooks/pre-commit
to include:
Now when I do a git commit
, Rubocop will run on my local files making sure I am not checking in files that are in violation.
Fixing Violation
Now that I am setup to have Rubocop police my programming, I can fix existing style violations in the code. The first and easiest to fix are violations that can be auto-corrected by Rubocop itself.
To do this, I open .rubocop_todo.yml
in my favorite editor (at the moment it is Atom). I search or scan this file for rules that have the comment “# Cop supports --auto-correct
” about them. For example:
# Offense count: 1
# Cop supports --auto-correct.
Lint/StringConversionInInterpolation:
Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
Lint/BlockAlignment:
Enabled: false
I comment out the first rule using the #
, like this:
# Offense count: 1
# Cop supports --auto-correct.
# Lint/StringConversionInInterpolation:
# Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
Lint/BlockAlignment:
Enabled: false
Next, I run Rubocop’s auto-correct feature from the command line and Rubocop shows me which files it corrects:
$ rubocop -a
Inspecting 71 files
..................................................W....................
Offenses:
spec/controllers/v1/widgets_controller_spec.rb:67:8: W: [Corrected] end at 67, 7 is not aligned with it 'has client url' do at 65, 6
end
^^^
71 files inspected, 1 offense detected, 1 offense corrected
Finally, I commit this change to git
with a note about the rule that was fixed:
$ git commit -m "Fix Lint/BlockAlignment violation found by Rubocop" spec/controllers/v1/widgets_controller_spec.rb
I then re-run the auto-gen command a get a new version of the .rubocop_todo.yml
that has this violation removed.
$ rubocop --auto-gen-config
$ git diff .rubocop_todo.yml
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 2f55803..e87e458 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,16 +1,11 @@
-# Offense count: 1
-# Cop supports --auto-correct.
-Lint/BlockAlignment:
- Enabled: false
-
This procedure can be repeated until most violations in the .rubocop_todo.yml
. Usually, I will wait until most are fixed before committing a new version of the .rubocop_todo.yml
.