RuboCop
by Željko Filipin
TLDR
RuboCop (GitHub, rubygems, ruby-toolbox) is a “Ruby static code analyzer”. Over 1 million downloads at rubygems.org. It’s popularity has doubled this year. It is the second most pupular tool in the code metrics category.
The problem
From community-driven Ruby coding style guide prelude:
One thing has always bothered me as a Ruby developer - Python developers have a great programming style reference (PEP-8) and we never got an official guide, documenting Ruby coding style and best practices. And I do believe that style matters.
At work, with just a few exceptions here and there, all code is reviewed (by somebody that did not write it) before it is merged into master branch. It is really useful if you can focus on giving meaningful comments when reviewing code, instead of getting distracted by trivial stuff like formatting.
The solution
RuboCop. Make it run after every commit and it will complain if anything obvious is wrong, so humans can focus on what the code should do.
Setup
The installation is trivial and explained in the readme file, so I will not cover it here.
Let’s pick a Ruby repository and make the code beautiful. For inspiration, let’s take a look at GitHub trending Ruby repositories for the last month. The most interesting one to me was jekyll, the tool I am using to write this blog post.
The first thing to do (after cloning a repository) is to run rubocop
, or bundle exec rubocop
(if you are using Bundler). If you run it in a repository that RuboCop has already cleaned up (for example, rubocop repository), output will look similar to this:
Things get more interesting if you run it in a repository that is not already cleaned up, for example jekyll:
3930 offenses! Where to even start? There is a nice command-line option:
Let’s try it:
Take a look at the file, it should look similar to this:
For now we will ignore the contents of the file. RuboCop createad .rubocop_todo.yml
file that lists all violations. The file on purpose has todo in the name, since it is supposed to be short lived, until the problems are resolved, not permanent.
Let’s do as suggested. All that needs to be done is to create the permanent configuration file named .rubocop.yml
. The only contents for now will be a note to inherit everything from the todo file: inherit_from: .rubocop_todo.yml
.
Let’s run RuboCop again.
At this point, RuboCop ignores all existing offenses, but it would complain if new offenses are introduced. Commit what you have so far.
Continuous Integration
This is a great time for setting up RuboCop to run after every commit to the repository. Since there are a lot of ways you could do that, let’s try setting up RuboCop to run in TravisCI.
It is as simple as adding gem "rubocop"
to the Gemfile
and adding bundle exec rubocop
to .travis.yml
.
Clean up
The next step is cleaning up. Open the .rubocop_todo.yml
file and take a closer look. Find an offense with low offense count (ideally 1) that supports --auto-correct
. This one looks good:
Delete the lines and run RuboCop again, this time with -a
(or --auto-correct
) flag.
Rubocop says it fixed the problem. Let’s see what happened.
RuboCop has changed exists?
to exist?
. A trivial change, but a step forward. This is another point where I would make a commit. (I like small commits.) Commit message can be simple:
RuboCop will not be able to fix all offenses, and those that are not fixed automatically tend to be the most interesting ones. For example, Lint/UselessAssignment will complain if variables are defined but not used (real life example).
I would suggest that you clean up the repository, one offense by one. Start with the ones that can be auto-corrected and that have a small number of offenses. Make a commit for every fixed offense. Stop when you get bored. You can always continue later.
Configuration
Style/StringLiterals is an interesting rule.
Ruby style guide says:
Adopt a consistent string literal quoting style. There are two popular styles in the Ruby community, both of which are considered good - single quotes by default (Option A) and double quotes by default (Option B).
The default is single quotes. But this repository uses double quotes and RuboCop reports almost 2000 offenses.
RuboCop can automatically change all double quotes to single quotes, but if you decide to continue using the current style (double quotes), delete the above lines from the .rubocop_todo.yml
file and put this into .rubocop.yml
file:
Let’s see the change:
RuboCop does not complain about double quotes any more, but now it complains about single qoutes. :)
As the style guide says, you should pick one style.
Misc
1 AD to 2003 AD Historical Trends in global distribution of GDP (China, India, Western Europe, USA, Middle East) is a really interesting graph.
tags: code - event - featured - ruby - speaker