Implementing rubocop to an existing (might be messy) project


Rubocop is powerful, but it is a pain in the ass if you take over an existing project. There might be hundreds of files that is badly formatted and you can't find a way to start. Here's how I find a starting point:

1. List all cops

Suppose you have installed gem 'rubocop'. Check the config directory in rubocop repo and copy all possible options into your .rubocop.yml (which should be in your project root directory). There are a whole bunch of options and may be troublesome for you, but this list allows you to see what cops you have turned on, especially if you're not familiar with this tool.

All options are listed on this file, and I have added some marks for better readability. Copy it at will.

2. Turn off all options

Use your text editor and replace all Enabled: true to Enabled: false. Run rubocop command, and there should be no error at all (since there is no check). OK, let's get started.

3. Start with the easiest

The easiest cops to start with are the cops that support auto-correction, which are prepended with # Supports --auto-correct comment. It is preferred to start with:

Lint/BlockAlignment:
  Description: "Align block ends correctly."
Lint/DefEndAlignment:
  Description: "Align ends corresponding to defs correctly."
Lint/EndAlignment:
  Description: "Align ends correctly."
Lint/SpaceBeforeFirstArg:
  Description: "Put a space between a method name and the first argument in a method call without parentheses."

These checking options have no influence the functionality of the codebase, and styles are non-controversial. Follow the following steps:

  1. Make the options Enabled: true to turn them on.
  2. Run rubocop -a to automatically correct all errors.
  3. Use git diff afterwards to ensure nothing is broken (which usually don't).

4. Go on with the less-controversial

If you're working in a team, communicate which to do next before any further implementation; however, I suggest serveral options that can easily reach consensus.

Lint/Debugger:
  Description: "Check for debugger calls."
Lint/DuplicateMethods:
  Description: "Check for duplicate methods calls."
Lint/DuplicatedKey:
  Description: "Check for duplicate keys in hash literals."  
Lint/EmptyEnsure:
  Description: "Checks for empty ensure block."
Lint/UselessSetterCall:
  Description: "Checks for useless setter call to a local variable."

These are less-controversial checks, for instances, only rare conditions require duplicate methods and keys in a hash, and you don't set an ensure block and leave it blank.

5. Select style, instead of file

One may ask that if it is good to start with specific files, for example, models in a Rails project. Don't do that. Style check should cover the whole project, or it will be hard to maintain. If a set of files are applied to one style check and another set is not, it is hard to run code review, integrations with CI and so on. You have to keep in mind which set of files are applied to which style check. It will be unnecessarily complicated.

6. And go on

Now you have implemented some checkers in your project. Go on with more complicated checks and you should be fine.