Improve your Ruby syntax with Rubocop

Fernando PeralesNov 29, 2013

As software developers, we are always trying to improve our projects: refactoring, updating gems, trying alternatives to make our applications faster and more reliable. But it seems that there is a topic about which it is very hard for us to come to an agreement: that's syntax.

Compare these classes:

class DummyClass

end

class SecondDummyClass
end

class AnotherDummyClass; end

class AThirdDummyClass;end

Which one do you think is the right one, and why? All of them are right: all of them will run without any problems in our projects. The problem arises when one of the developers in your team uses the first one and you use the third one, but your client likes the fourth one and your Project Manager the second one: everyone will try to make the others use the syntax they like.

Introducing Rubocop

Rubocop is a code analyzer whose purpose is to force you to write code that follows the style guide dictated by the Ruby community.

Quickstart

Let's install Rubocop

gem install rubocop

You can run Rubocop directly in your app directory

cd your_app
rubocop

But be careful: this will review ALL of your Ruby files in your application including gems. So you might want to be more selective about what to scan, and you can do it by sending an extra param to the rubocop command

rubocop app

This will make Rubocop scan only the app directory. If we want to scan more files or directories, we can pass them as params

rubocop app spec config/application.rb

Hands on

Let's do an example with this smelly code found in example\of_bad_code.rb_

class A_bad_named_class

    def ABadNamed_Method
        a = 2
    if a
      a+=1
    return true
    else
      return false
    end
      return false
    end   
end 

Now we run

rubocop example_of_bad_code.rb

As soon as Rubocop finishes inspecting the files, we will get an output similar to this:

Inspecting 1 file
W

Offences:

example.rb:1:1: C: Missing top-level class documentation comment.
class A_bad_named_class
^^^^^
example.rb:1:7: C: Use CamelCase for classes and modules.
class A_bad_named_class
      ^^^^^^^^^^^^^^^^^
example.rb:3:7: C: Use snake_case for methods.
  def ABadNamed_Method
      ^^^^^^^^^^^^^^^^
example.rb:6:7: W: Useless assignment to variable - a
      a+=1
      ^
example.rb:6:8: C: Surrounding space missing for operator '+='.
      a+=1
       ^^
example.rb:11:7: C: Redundant `return` detected.
      return false
      ^^^^^^
example.rb:12:5: W: end at 12, 4 is not aligned with def at 3, 2
    end
    ^^^

1 file inspected, 7 offences detected

The default output is a complete list of the problems found in our code.

The previous case showed 7 errors in a single file and the output is still easy to handle. But, what can we do when Rubocop reports hundred of errors?

Get in format with formatters

Rubocop provides us with a lot of formatters that display the output in different ways. We can specify the output format from the console by using the --format option:

The formatter I have found more useful is the offences formatter

rubocop example_of_bad_code.rb --format offences

Now the output will look like this:

1  EndAlignment
1  RedundantReturn
1  SpaceAroundOperators
1  UselessAssignment
1  MethodName
1  ClassAndModuleCamelCase
1  Documentation

As you may have guessed, this formatter groups the offences into categories and gives us a good overview of our project.

Cops and donuts

Now that we have an idea about what is wrong with our syntax, it's time to start taking a more detailed look to the cops. In Rubocop, a cop is the name of the specific 'error' presented in our code (i.e. EndAlignment cop tells us that an 'end' keyword is not properly aligned with its opening keyword)

Cops are divided into 3 types: Lint, Rails and Style

If we want to see a complete list of available cops, we can do it by running:

rubocop --show-cops

No offences allowed

By knowing the name of the cops, we can look up for a specific cop in our code by running:

rubocop --only EndAlignment

On the other hand, we might consider not to pay attention to certain cops. But, how can we exclude them from the analysis?

Setting a default behavior

The behavior of the analysis can be controlled via rubocop.yml, a file that can be placed in the root of your project or your home directory.

For example, to change the default line length in the LineLength cop from 79 to 60, we can add this to our Rubocop file:

LineLength:
  Max: 60

A complete list of cops and configuration options is found in the list of cops --show-cops

Fix all the things!

One of the coolest features in Rubocop is its ability to automatically fix certain kind of errors with the --auto-correct option

Before using this option, I really encourage you to stage the actual status of your project, just in case something goes wrong with the autocorrection:

rubocop --auto-correct    

Once that we have checked that the autocorrection didn't mess up our code, we can start fixing any remaining offences by hand.

Final words

Remember that these standards are outlined by the Ruby community and it is up to you to decide if each particular kind of offence is relevant to your project. You can find more information in the official repository. Thanks for reading!

blog comments powered byDisqus