Rubocop is an incredibly popular Ruby gem for linting Ruby code. With very little configuration, Rubocop scans a repository for violations of the Ruby community’s style standards. In many cases, it can even autocorrect violations, which Rubocop calls “offenses”.
Rubocop can be configured to run in a continuous integration pipeline, ensuring that code meets a given set of standards before merging into the main branch. You can also run Rubocop locally, in a container, or even with the VS Code extension. Many high-performing teams find this helpful in enforcing team standards, given Rubocop’s flexibility with rule configurations that allow for custom rules.
Rubocop (by default) scans an entire project, so the time it takes to run will increase with the size of the project, which could slow down CI builds. Many teams find this to be a fair trade-off given the benefits of using Rubocop in a project.
Adding Rubocop to an existing app
Adding Rubocop to an existing application is easy in theory, but can quickly become overwhelming if the project in question does not meet the style guidelines. Fortunately, Rubocop can address one violation at a time.
To add Rubocop to a Ruby on Rails application, begin by adding it to the Gemfile:
gem 'rubocop', require: false
Then, run:
bundle install
Next, to run Rubocop, in your project directory simply run:
bundle exec rubocop
Unless you’re really lucky, an existing project will probably have a number of violations. Fitting with the theme, Rubocop calls these style violations “Offenses”.
You can organize Rubocop’s output by running:
bundle exec rubocop --format offenses
Automatically correcting offenses
If you like, Rubocop can actually automatically correct a great deal of violations, just by passing the autocorrect flag:
bundle exec rubocop -a
Many choose to automatically correct these types of offenses to reduce the burden of making such a high volume of minor changes to satisfy code standards. If you do auto-correct changes, it’s wise to double check the diff before making any commits.
Ignoring existing violations
When adding Rubocop to a new project, you may find that the number of existing violations is overwhelming.
Many choose to start by excluding existing violations, only failing checks for new occurrences. This is a great way to ensure that new code meets standards, but product work does not have to stop entirely while old code is refactored.
To ignore existing violations, just run:
bundle exec rubocop --auto-gen-config
This runs Rubocop, and generates a new file, .rubocop_todo.yml
. This creates a list of exclusions that tell Rubocop what to ignore, but also serves to remind you what is left to fix.
If you run Rubocop again, you’ll see that there are NO offenses!
Now your team can go through and make more manageable changes while removing exclusions from the Rubocop todo file.
Changing rules to fit team standards
Rubocop defaults to the Ruby standard style guide, which some teams may want to deviate from. Style standards are an important part of a healthy engineering culture, and naturally Rubocop allows for customization.
Rubocop gets its configuration from the automatically generated .rubocop.yml
file. If you’ve already run Rubocop with --auto-gen-config
, then your configuration file is set to inherit from it. This works because the rubocop_todo.yml
file is just a fancy configuration file, so the main configuration file can inherit from it.
.rubocop_todo.yml
provides good examples of rules being changed. If you want to exclude specific files or directories from failing a particular rule, you can do so like this:
Layout/EmptyLinesAroundClassBody:
Exclude:
- 'app/controllers/checkout_controller.rb'
This particular configuration excludes the file named app/controllers/checkout_controller.rb
from failing the Layout/EmptyLinesAroundClassBody
check.
You can also override the values that checks specifically look for. One such example is method length, where you can set the maximum accepted lines in a method in your project by adding the following to your config:
Metrics/MethodLength:
Max: 24
You can disable specific rules as well. This example disables the Style/StringLiterals
check for the whole project:
Style/StringLiterals:
Enabled: false
Setting custom style standards in the codebase itself is a great way to ensure that entire teams have a say in the decisions regarding style. Opening a pull request to change the style standards ensures that developers get a chance to review and comment, and also doesn’t disrupt their workflow
You can even create a custom check, but the complexity around that is a bit beyond the scope of this article.
Running Rubocop in Semaphore
Running Rubocop in continuous integration is a common way to enforce that style standards are met before code is merged. This is pretty easy to do with Semaphore.
Next, sign up for Semaphore – it’s fastest to sign up with Github to save some Github configuration later. The hobby plan will fit our needs for this example. Click “Create New”, and select “Choose Repository” to connect Semaphore to your existing Github repository.Select the basic “Ruby on Rails” workflow and edit it to add a line for bundle exec rubocop
:
checkout
sem-version ruby 2.6.5
cache restore
bundle install --deployment --path vendor/bundle
cache store
bundle exec rubocop
Alternatively, you can add bundle exec rubocop
to almost any existing CI configuration just as easily.
Rubocop helps your team decide on and enforce code standards in Ruby projects, which will undoubtedly improve the quality of your codebase over time. Running Rubocop in CI forces code that gets merged into the master branch to conform to standards. Pairing this with Rubocop’s flexibility in rules allows teams to incrementally improve a codebase without becoming overwhelmed. In this article, you’ve seen how easy it is to add Rubocop to an existing codebase, even if style violations are everywhere. Add Rubocop to your Rails applications today for incremental improvements on the style of your code!