10 Rubocop Rules for Clearer and Higher-Quality Ruby Code

You’ve finally decided to add RuboCop to your project. You add the gem, run the “rubocop” command for the first time, and get something like this:

And now what?… What is an offense? What isn’t? Can you change these rules?

I spent a lot of time trying to understand all the different rules and find the ones I needed, so I’m here to help you avoid the same fate. In this article, I’ll explain the key RuboCop rules and how to customize the tool to fit your project’s needs.

What is an ‘offense’ in RuboCop?

RuboCop is a static code analyzer and formatter for Ruby that enforces coding standards and style guidelines by checking your code against a set of predefined rules.

When it detects code that doesn’t conform to these rules, it registers an offense.

Offenses can range from minor stylistic issues, such as incorrect indentation or trailing whitespace, to more significant problems like code complexity or security vulnerabilities. Each offense is accompanied by a message describing the issue and often includes suggestions for how to fix it.

Given that each organization has its own conventions and programming preferences, RuboCop’s flexibility allows you to customize the rules and severity of offenses according to your project’s specific needs. To achieve this, you need to create a rubocop.yml file in the root of your project, indicating which rules you want to override (considering that these are the default rules).

As an example, this is the configuration file we wrote for our API.

10 Key RuboCop Rules

There are many different rules that we can apply to our code with Rubocop, but here are the 10 that I found most valuable and frequent in my projects:

  1. Layout/LineLength: Enforces a maximum line length to keep code readable and avoid horizontal scrolling.
# Bad
puts "This is a very long line that exceeds the maximum length set by Rubocop, making it hard to read."

# Good
puts "This line is within the maximum length and is easier to read."
Example of LineLength

2. Style/StringLiterals: Enforces consistent use of single or double quotes for string literals to maintain code style.

# Bad
str1 = "This is a string using double quotes."
str2 = 'This is a string using single quotes.'

# Good
str1 = 'This is a string using single quotes.'
str2 = 'This is another string using single quotes.'
Example of StringLiterals

3. Layout/TrailingWhitespace: Flags trailing whitespace at the end of lines to keep code clean and avoid unnecessary characters. In the following example there are 2 whitespaces after the “end” word.

Example of TrailingWhitespace

4. Style/TrailingCommaInArrayLiteral: Requires or forbids trailing commas in array literals for consistent formatting.

# Bad (if trailing comma is not required)
array = [
1,
2,
]

# Good
array = [
1,
2
]
Example of TrailingCommaInArrayLiteral

5. Layout/HashAlignment: Enforces consistent alignment of keys and values in hash literals.

  • EnforcedColonStyle: Determines how colons in hashes are aligned. The table style aligns keys and values to the left.
# EnforcedColonStyle: table

# Bad
hash = {
key1: "value1",
val: "value2",
}

# Good
hash = {
key1: "value1",
val: "value2",
}
  • EnforcedHashRocketStyle: Specifies the alignment for hash rockets (=>). The table style aligns hash rockets vertically.
# EnforcedHashRocketStyle: table

# Bad
hash = {
key1 => "value1",
val => "value2",
}

# Good
hash = {
key1 => "value1",
val => "value2",
}
Example of HashAlignment

6. Lint/RescueWithoutErrorClass: Discourages rescuing exceptions without specifying an error class to avoid catching unexpected errors.

# Bad
begin
# some code
rescue
# handle error
end

# Good
begin
# some code
rescue StandardError
# handle error
end
Example of RescueWithoutErrorClass

7. Naming/MethodName: Enforces naming conventions for methods to ensure consistency and clarity.

# Bad (the rule enforces snake_case by default)
def SomeMethodName
# code here
end

# Good
def some_method_name
# code here
end
Example of MethodName

8. Lint/UselessAssignment: Detects and flags unnecessary variable assignments, helping to clean up redundant code.

# Bad
unused_variable = 42
puts "Hello, world!"

# Good
puts "Hello, world!"
Example of UselessAssignment

9. Style/SymbolArray: Enforces consistent syntax for arrays of symbols, preferring the newer %i notation for conciseness.

# Bad (Old Syntax)
symbols = [:foo, :bar, :baz]

# Good (New Syntax)
symbols = %i[foo bar baz]
Example of SymbolArray

10. Naming/RescuedExceptionsVariableName: Ensures rescued exception variable names are consistent and meaningful.

# Bad
rescue => ex
puts ex.message

# Good
rescue => e
puts e.message
Example of RescuedExceptionsVariableName

Beyond the default rules and the ones I explained here, I invite you to analyze the needs of your particular project and review the official Rubocop documentation to see what other rules might work for you.

By understanding and configuring them, you can ensure your Ruby code remains clean, consistent, and maintainable ✨.