Rubocop and Rails: Keeping Up-to-date
Updating your Rails application and workflow with the latest Rubocop release
Integrating rubocop into your Rails application work flow is just the beginning. This is not a “set-it-and-forget-it” relationship. Ruby is continually evolving and so is the style guide. Thankfully there is an active community committed to keeping rubocop up-to-the-minute.
Because rubocop updates are happening so rapidly, the README suggests locking the rubocop version in your
Gemfile to avoid breaking change surprises. Not a bad idea since they’re not kidding about rapid changes but keep in mind that you miss out on all the benefits of a linter if you let it get too out-of-date. (Right?)
Not all of the following step are strictly necessary but the goal here is a full, explore all the corners, clear out the cobwebs update.
Btw, if you haven’t previously installed added rubocop to your Rails application I suggest checking out a previous blog post about getting started with rubocop first.
Okay, let’s get started:
Create a solid starting point
- Commit or discard any uncommitted changes. Use a “WIP” commit if you need to.
git diffis going to be your new best friend.
Although working in a new branch is also a good idea, you are potentially about to modify a whole lot of files. Merging the branch back in could be painful if you’re uncertain of your starting point.
- If you are still using a
.rubocop_todo.ymlfile, now is the time to finish handling what’s outstanding. The
.rubocop_todo.ymlfile is going to be overwritten later on.
- If it’s not already under source control, make a backup copy of
.rubocop.ymlfor safe keeping.
Update your rubocop version
- Update the rubocop gem. If necessary, don’t forget to unlock the version in your
1gem update rubocop1bundle update rubocop
- Check rubocop will be using the right target Ruby version.
Start setting up the .rubocop.yml file
Sometimes when new cops are added, they are disabled by default. These need to be included in the update to look for anything interesting and/or useful.
At some point in the future (and I’ll update this section when/if it happens), we’ll be able to set the reverse of
DisabledByDefault to automatically enable all cops by default. But in the meantime, it’s not that hard to do by hand.
- At the bottom of the
.rubocop.ymlfile, add lines of comments for an obvious visual demarcation between the existing configuration and what we’re about to add. (Sounds trivial but trust me it will help with all the cut and paste.)
config/disabled.ymlin the github.com repository for rubocop. Copy the contents of the file into the bottom of the
.rubocop.ymlfile below the demarcation line of comments.
- Edit the section of text you just added:
- Delete the lines
Rails: Enabled: false.
- Remove any cops that are duplicates. In other words, already listed above the demarcation line.
- Go through and flip the
- Delete the lines
(Hint: To grab a single file from a github.com repository, hit the Raw button, then copy and paste from the browser.)
Generate a TODO list to work against
- Now that
.rubocop.ymlis set-up to catch any new but disabled cops and we have the latest rubocop version installed, it’s time to create a TODO configuration file
.rubocop_todo.ymljust like we did when doing the initial integration.
- This is important. Once you have a
.rubocop_todo.ymlfile, comment out the section you added to the bottom of the
.rubocop.ymlfile. You want these cops to now be pulled in from the
- Add the line
Work through the TODO list
Now begins the process of working through each cop in
.rubocop_todo.yml. Iterating through the updates. This should be a familiar process and hopefully much less painful that the initial rubocop integration (as long as you’ve been keeping up with the updates!) I wrote more about this process in a previous blog post.
Some Additional Thoughts
- Seriously. No matter how tempting. Do not just blindly run the auto correct without understanding what you’re correcting. This can lead to unpleasant surprises. Plus part of this process is learning where your code is deviating from the ruby style guide and understanding why.
- Review the CHANGELOG. Even a quick read could alert you to something related to the settings in your
.rubocop.ymlthat you need to update.
- In particular, this is a good time to review the cops that are disabled. Could be that a change was made that would now allow you to enabled it with some configuration.
- Review for extra
.rubocop.ymlfiles in sub-directories that can be eliminated. For example, rather than having a
.rubocop.ymlfile in the
./specsdirectory to turn off cops that don’t work for Rspec, exclude the
./specsdirectory in the main
.rubocop.ymlfile.1234Rails/SkipsModelValidations:Enabled: trueExclude:- 'spec/**/*.rb'
- Don’t forget to also review the cops disabled inline in the code.
1grep -r "rubocop:dis" .
For example, if a cop is disabled at the top of the source file consider excluding the file specifically in
.rubocop.ymlinstead of have a “magic comment” in the source file.
- For the cops from
config/disabled.yml, in the interest of not duplicating work during the next update, enable or disable them in your
.rubocop.ymlfile now. For example, if you know that you’re never going to be adding a copyright message to every file, disable
Style/Copyrightso you know to ignore it next time.
- If you really want to geek out, not just the CHANGELOG but the open issues and pull requests as well as the repository change histories make for interesting reading. (Just saying.)
A Final Thought
If rubocop is a valuable part of your workflow (and if you’re still reading at this point, how could it not be), consider making a donation or becoming a sponsor.