Back to Scaling Ruby Applications guides

Using RuboCop for Effective Ruby Code Linting

Ayooluwa Isaiah
Updated on February 22, 2025

Ruby's flexible syntax is both a blessing and a curse. While it enables elegant and expressive code, it can also lead to inconsistent codebases when multiple developers are involved.

Enter RuboCop - the de facto standard for Ruby code linting and static analysis. This article will guide you through effectively using RuboCop to maintain consistent, high-quality Ruby code.

What is RuboCop?

RuboCop serves two primary purposes:

  1. Code style enforcement through configurable rules called "cops".
  2. Static code analysis to identify potential issues and complexity concerns

The tool helps maintain consistency across your codebase, reducing cognitive load for developers and making code more maintainable. It's particularly valuable in team environments where establishing and enforcing common conventions is crucial.

Getting Started with RuboCop

You can install RuboCop via RubyGems:

 
gem install rubocop

For projects using Bundler, add to your Gemfile:

 
group :development, :test do
  gem 'rubocop', require: false
end

To analyze your entire code, run RuboCop from your project's root directory:

 
bundle exec rubocop

Or provide a list of files and directories that should be analyzed:

 
bundle exec rubocop src/pkg

When you run RuboCop without any custom configuration, it enforces a default set of rules based on the Ruby Style Guide created by the community. Running RuboCop on your code will show any violations, called "offenses." For each offense, RuboCop provides:

  • The exact location (file and line number)
  • A clear description of what's wrong
  • The specific rule that was violated
  • Whether the offense can be automatically fixed

For example, if RuboCop finds a line that's too long, it might show:

 
app/models/user.rb:15:81: C: [Correctable] Layout/LineLength: Line is too long. [150/120]

1.png

This detailed output helps you quickly locate and fix style violations in your code.

After analyzing your code, RuboCop provides a summary at the bottom that shows:

  • Total number of files it checked
  • How many violations it found
  • How many of these violations it can fix automatically

For example:

 
20 files inspected, 15 offenses detected, 12 offenses autocorrectable

To have RuboCop automatically fix the correctable violations, run:

 
rubocop -a

When using auto-correct, RuboCop will only fix violations marked as [Correctable] in its output. These are changes that RuboCop can safely make without risking changes to your code's behavior. For more aggressive auto-correction that might affect code behavior, use rubocop -A instead.

2.png

Understanding RuboCop's Cops

RuboCop organizes its rules into logical departments, each focusing on different aspects of code quality. Understanding these departments helps you better configure and use the tool.

Here are some of the most commonly used departments:

1. Style cops

Style cops enforce Ruby style guide conventions and best practices, ensuring consistency in string literal formatting, method definitions, conditional expressions, and collection syntax. For example, configuring string literals can be done as follows:

 
Style/StringLiterals:
  EnforcedStyle: single_quotes

Similarly, enforcing parentheses in method definitions can be configured as:

 
Style/MethodDefParentheses:
  EnforcedStyle: require_parentheses

2. Layout cops

Layout cops deal with the visual presentation of the code, focusing on indentation, line length, spacing around operators, and empty lines. The following example sets a maximum line length of 100 and an indentation width of 2:

 
Layout/LineLength:
  Max: 100

Layout/IndentationWidth:
  Width: 2

3. Lint cops

Lint cops detect potential errors and suspicious constructs, such as unused variables, dead code, syntax issues, and common programming mistakes. Enabling linting for unused method arguments while ignoring empty methods can be achieved through:

 
Lint/UnusedMethodArgument:
  Enabled: true
  IgnoreEmptyMethods: true

4 Metric cops

Metrics cops measure code complexity, analyzing factors like method length, class length, cyclomatic complexity, parameter lists, and block nesting. To limit method length to 20 and class length to 300, the following configuration can be used:

 
Metrics/MethodLength:
  Max: 20

Metrics/ClassLength:
  Max: 300

5. Naming cops

Naming cops ensure adherence to naming conventions for variables, methods, classes, and modules. A consistent naming style, such as enforcing snake_case for method and variable names, can be set as follows:

 
Naming/MethodName:
  EnforcedStyle: snake_case

Naming/VariableName:
  EnforcedStyle: snake_case

There are also Gemspec, Migration, Security, and Bundler cops available.

By understanding and configuring these departments appropriately, RuboCop can be tailored to enforce code consistency and maintain high-quality Ruby codebases.

Configuring RuboCop

RuboCop uses a YAML configuration file named .rubocop.yml placed in your project's root directory. This file lets you customize RuboCop's behavior for your specific project. You can also set up global configurations:

  • ~/.rubocop.yml in your home directory.
  • ~/.config/rubocop/config.yml in the XDG config directory.

These global configs apply when a project doesn't have its own .rubocop.yml file.

RuboCop's default rules live in ~/.config/rubocop/default.yml. Your project's configuration inherits from these defaults, so you only need to specify rules that differ from the defaults.

You can extend RuboCop's functionality through additional gems:

Gemfile
# Gemfile
gem 'rubocop-rails'
gem 'rubocop-rspec'
gem 'rubocop-performance'

When RuboCop releases new cops, they start in "pending" status. Enable them all with:

 
# .rubocop.yml
AllCops:
  NewCops: enable

Adding RuboCop to Legacy Projects

Legacy Ruby projects often have numerous style violations that can't be fixed immediately. RuboCop provides a way to gradually improve code quality by generating an allowlist of existing offenses. This lets you:

  • Track existing violations
  • Prevent new violations
  • Fix issues incrementally

Running RuboCop on a legacy project typically shows many violations:

 
bundle exec rubocop
Output
232 files inspected, 1230 offenses detected

Generate a todo list of current violations:

 
bundle exec rubocop --auto-gen-config
Output
Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`.
Created .rubocop_todo.yml.

This creates .rubocop_todo.yml containing all current violations. RuboCop updates .rubocop.yml to inherit from this file, so running RuboCop again shows:

Output
232 files inspected, no offenses detected

By default, RuboCop disables cops with more than 15 violations. To prevent this behavior and ensure all cops remain active regardless of violation count, use:

 
bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1000

This command creates Exclude blocks listing violating files rather than disabling cops entirely. Setting a high exclude limit ensures all cops stay enabled and new code follows the standards, while existing violations can be addressed over time.

The cleanup process involves selecting a file from an Exclude block in the todo list, fixing its violations, and running the test suite to ensure no bugs were introduced.

After committing these changes, you can move on to the next file. When all files for a particular cop have been fixed, you can remove that cop from .rubocop_todo.yml or regenerate the todo list to track your progress.

Remember to use rubocop -a for automatic fixes when possible, as this can significantly speed up the cleanup process.

Handling RuboCop violations

While RuboCop is a valuable tool, it occasionally produces false positives or suggests changes that could harm code readability or functionality. You can selectively disable RuboCop checks using special comments in your code.

To disable specific cops for a section of code:

 
# rubocop:disable Layout/LineLength, Style
. . .
# rubocop:enable Layout/LineLength, Style

To disable all cops for a section, use:

 
# rubocop:disable all
. . .
# rubocop:enable all

For single-line violations, use an end-of-line comment:

 
@My_var = 0 # rubocop:disable Naming/MethodName

Editor integration

Most popular editors support real-time RuboCop integration, showing violations as you type rather than requiring command-line checks.

For example, if you're on VS Code, install the Rubocop extension and configure it in your settings.json file:

 
"[ruby]": {
  "editor.defaultFormatter": "rubocop.vscode-rubocop"
},

3.png

Git pre-commit hooks with RuboCop

Pre-commit hooks ensure code quality by running RuboCop before code reaches your repository. By checking code style and potential issues before each commit, you can maintain consistent code quality across your project. While there are several ways to implement pre-commit hooks, we'll focus on a simple but effective approach.

First, create a pre-commit hook file:

 
#!/bin/sh
# .git/hooks/pre-commit

FILES=$(git diff --staged --name-only --diff-filter=d | grep '.rb$')

if [ -n "$FILES" ]; then
  bundle exec rubocop $FILES
  if [ $? -ne 0 ]; then
    echo "RuboCop found style violations. Please fix them before committing."
    exit 1
  fi
fi

Make the hook executable:

 
chmod +x .git/hooks/pre-commit

This script runs RuboCop only on staged Ruby files, making it efficient for large projects. If RuboCop finds any violations, the commit will be blocked until the issues are fixed.

4.png

For work in progress that needs temporary commits, you can bypass the hook:

 
git commit --no-verify -m "WIP: temporary commit"

You might also want to add specific configurations for your pre-commit RuboCop checks by creating a dedicated configuration file:

 
# .rubocop_precommit.yml
inherit_from: .rubocop.yml

# Stricter rules for pre-commit checks
Layout/LineLength:
  Max: 80

Style/Documentation:
  Enabled: true

Then update your pre-commit hook to use this configuration:

 
bundle exec rubocop --config .rubocop_precommit.yml $FILES

This setup provides a solid foundation for maintaining code quality while remaining flexible enough for real-world development needs.

Adding RuboCop to your CI pipeline

5.png

Running RuboCop in your continuous integration pipeline helps catch style violations before they reach your main branch. Let's set this up using GitHub Actions.

Create a new workflow file:

.github/workflows/lint.yml
name: Lint

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  rubocop:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true

      - name: Run RuboCop
        run: |
          bundle exec rubocop --parallel
          bundle exec rubocop --format github
        # You can also use: https://github.com/reviewdog/action-rubocop

This workflow runs whenever code is pushed to main or when a pull request targets main. The job runs on Ubuntu and:

  • Checks out your code
  • Sets up Ruby with dependency caching
  • Runs RuboCop in parallel for speed
  • Outputs results in GitHub-friendly format

For better visibility, you can add RuboCop's results as annotations:

 
- name: RuboCop Report
  run: |
    echo "::group::RuboCop Results"
    bundle exec rubocop --format progress --format json --out tmp/rubocop.json
    echo "::endgroup::"

With this setup, style violations will appear directly in your pull requests, making it easy for developers to fix issues before merging.

Final thoughts

RuboCop is an essential tool in modern Ruby development, promoting code quality and consistency across teams and projects. While the initial setup and configuration might require some investment, the long-term benefits of standardized code style and early error detection make it invaluable.

Remember that while RuboCop is highly configurable, the goal is to spend more time writing features and less time debating style choices. Consider adopting existing style guides or using Standard Ruby if extensive configuration seems overwhelming.

For up-to-date information and detailed documentation, visit the RuboCop documentation. Thanks for reading!

Author's avatar
Article by
Ayooluwa Isaiah
Ayo is a technical content manager at Better Stack. His passion is simplifying and communicating complex technical ideas effectively. His work was featured on several esteemed publications including LWN.net, Digital Ocean, and CSS-Tricks. When he's not writing or coding, he loves to travel, bike, and play tennis.
Got an article suggestion? Let us know
Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Make your mark

Join the writer's program

Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.

Write for us
Writer of the month
Marin Bezhanov
Marin is a software engineer and architect with a broad range of experience working...
Build on top of Better Stack

Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.

community@betterstack.com

or submit a pull request and help us build better products for everyone.

See the full list of amazing projects on github