Linting and Auto-formatting Ruby Code With RuboCop

What if you could write sloppy code and have Ruby fix it for you automatically? With RuboCop, you can! Of course, linters and auto-formatters have other benefits, even if your code is pristine. Join Ayooluwa Isaiah for a tour of RuboCop.

Linting is the automated checking of source code for programmatic and stylistic errors. This checking is performed by a static code analysis tool called a linter. A code formatter, however, is a tool concerned with formatting source code so that it strictly adheres to a pre-configured set of rules. A linter will typically report violations, but it's usually up to the programmer to fix the problem, while a code formatter tends to apply its rules directly to the source code, thus correcting formatting mistakes automatically.

The task of creating a more consistent code style in a project usually necessitates the introduction of a separate linting and formatting tools, but in some cases, a single tool will be capable of addressing both concerns. A good example of the latter is RuboCop, which is the tool we'll consider extensively in this article. You'll learn how to set it up in your Ruby project and adjust its configuration options so that its output matches your expectations. Aside from integrating it into your local development process, you'll also learn how to make it a part of your continuous integration workflow.

Installing RuboCop

Installing RuboCop is straightforward through RubyGems:

$ gem install rubocop

Check the version that was installed:

$ rubocop --version

If you'd rather use Bundler, place the snippet below in your Gemfile and then run bundle install. The require: false part tells Bundler.require not to require that specific gem in your code since it will only be used from the command line.

gem 'rubocop', require: false

Check the version that was installed:

$ bundle exec rubocop --version

Running RuboCop

You can run RuboCop using its default settings on your project by typing rubocop (or bundle exec rubocop if installed with Bundler). If you don't pass any arguments to the command, it will check all the Ruby source files in the current directory, as well as all sub directories. Alternatively, you may pass a list of files and directories that should be analyzed.

$ bundle exec rubocop
$ bundle exec rubocop src/lib

Without any configuration, RuboCop enforces many of the guidelines outlined in the community-driven Ruby Style Guide. After running the command, you may get several errors (offenses). Each reported offense is decorated with all the information necessary to resolve it, such as a description of the offense, and the file and line number where it occurred.

Terminal showing RuboCop offenses

At the bottom of the report, you'll see a line describing the number of inspected files, the total number of offenses, and how many of the offenses can be fixed automatically. If you append the -a or --auto-correct argument, RuboCop will try to automatically correct the problems found in your source files (those prefixed with [Correctable]).

$ bundle exec rubocop -a

Terminal showing the RuboCop autocorrect feature

Notice how each corrected offense is now prefixed with [Corrected]. A summary of the number of corrected offenses is also presented at the bottom of the report. In the above example, there's another correctable offense that wasn't auto-fixed, even after appending the -a flag. This is because some automatic corrections might change the semantics of the code slightly, so RuboCop considers it to be unsafe. If you want to autocorrect these offenses as well, use the -A or --auto-correct-all flag.

$ bundle exec rubocop -A

Terminal showing RuboCop autocorrecting unsafe cops

A good rule of thumb to follow is to run your test suite after using the autocorrect functionality to ensure that the behavior of your code hasn't changed unexpectedly.

Configuring RuboCop

RuboCop can be configured through a .rubocop.yml file placed at the root of your project. If you want to use the same checks for all projects, you can place a global config file in your home directory (~/.rubocop.yml) or XDG config directory (~/.config/rubocop/config.yml). This global config file will be used if a locally scoped project configuration file is not found in the current directory or successive parent directories.

The default configuration for RuboCop is placed in its configuration home directory (~/.config/rubocop/default.yml), and all other config files inherit from it. This means that when setting up your project configuration, you only need to make changes that are different from the default. This could mean enabling or disable certain checks or altering their behavior if they accept any parameters.

RuboCop refers to each individual check as cops, and each one is responsible for detecting a specific offense. The available cops are also grouped into the following departments:

  • Style cops are mostly based on the aforementioned Ruby Style Guide, and they check the consistency of your code.
  • Layout cops catch issues related to formatting, such as the use of white space.
  • Lint cops detect possible errors in your code, similar to ruby -w, but with a host of additional checks.
  • Metric cops deals with issues related to source code measurements such as class length and method length.
  • Naming cops are concerned with naming conventions.
  • Security cops help with catching potential security issues.
  • Bundler cops check for bad practices in Bundler files (such as Gemfile).
  • Gemspec cops check for bad practices in .gemspec files.

It's also possible to extend RuboCop through additional linters and formatters. You can build your own extensions or take advantage of existing ones if they are relevant to your project. For example, a Rails extension is available for the purpose of enforcing Rails best practices and coding conventions.

RuboCop messages

When you create your configuration file for the first time, you'll get a slew of messages warning you about the presence of new cops that were added but not configured. This is because RuboCop adds new cops on each release, and these are set to a special pending status until they are explicitly enabled or disabled in the user configuration. You can enable or disable each of the listed cops in the message individually or use the snippet below to enable all new cops (recommended). Afterwards, the messages will be suppressed.

# .rubocop.yml
  NewCops: enable

If you don't want to fiddle with configuration files and the wealth of options provided by RuboCop, consider taking a look at the Standard project. It's largely a pre-configured version of RuboCop that aims to enforce a consistent style in your Ruby project without allowing the customization of any of its rules. The lightning talk where it was first announced gives more details about its origin and motivations.

You can install it by adding the following line to your Gemfile and then run bundle install.

# Gemfile
gem "standard", group: [:development, :test]

Afterwards, you can execute Standard from the command line as follows:

$ bundle exec standardrb

Adding RuboCop to an Existing Project

Most Rubyists do not have the luxury of working on greenfield projects. Much of our development time is spent in legacy codebases that may produce an overwhelming amount of linting offenses that cannot be tackled immediately. Fortunately, RuboCop has a useful feature that generates an allowlist of existing offenses, which can be addressed slowly over time. The benefit is that it allows you to introduce linting to your existing project without being bombarded with a mountain of unmanageable linting errors while flagging any new violations going forward.

$ bundle exec rubocop

523 files inspected, 1018 offenses detected

Creating the allowlist config file can be done through the command below:

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

The --auto-gen-config option collects all offenses and their counts and generates a .rubocop_todo.yml file in the current directory where all the current offenses are ignored. Finally, it causes .rubocop.yml to inherit from the .rubocop_todo.yml file so that running RuboCop on the codebase once again will not yield any offenses.

$ bundle exec rubocop
523 files inspected, no offenses detected

While generating the allowlist file, RuboCop will turn off a cop altogether if the number of violations exceeds a certain threshold (15 by default). This is typically not what you want because it prevents new code from being checked against that cop due to the number of existing violations. Fortunately, it's possible to increase the threshold so that cops are not disabled even if the number of violations is high.

$ bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000

The --auto-gen-only-exclude option ensures that each cop in the allowlist has an Exclude block that lists all the files where a violation occurred, instead of Max, which sets the maximum number of excluded files for a cop. Setting the --exclude-limit also changes the maximum number of files that can be added to the Exclude block for each cop. Specifying an arbitrary number larger than the total number of files being examined ensures that no cops will be disabled outright, and any new code added to existing or new files will be checked accordingly.

Fixing Existing Violations

After generating the .rubocop_todo.yml file, it's important not to forget the existing violations, but to slowly address them one after the other. You can do this by removing a file from the Exclude block of a cop, then fix the reported violations, run your test suite to avoid introducing bugs, and commit. Once you've removed all the files from a cop, you can delete the cop from the file manually, or regenerate the allowlist file once again. Don't forget to utilize the --auto-correct option where possible to make the process much faster.

Adopting a Style Guide

RuboCop is very configurable, which makes it viable for any type of project. However, it may take a long time to configure the rules to your requirements, especially if you disagree with many of the default rules. In such circumstances, adopting an existing style guide may be beneficial. Several companies have already released their Ruby style guides for public consumption, such as Shopify and Airbnb. Utilizing your preferred style guide in RuboCop can be achieved by adding the relevant gem to your Gemfile:

# Gemfile
gem "rubocop-shopify", require: false

Then, require it in your project configuration:

# .rubocop.yml
  rubocop-shopify: rubocop.yml

Suppressing Linting Errors

Although RuboCop is great tool, it can yield false positives from time to time or suggest fixing the code in a way that is detrimental to the intent of the programmer. When such situations arise, you can ignore the violation with a comment in the source code. You can mention the individual cops or departments to be disabled, as shown below:

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

Or you can disable all cops for a section of the code in one fell swoop:

# rubocop:disable all
# rubocop:enable all

If you use an end of line comment, the specified cops will be disabled on that line alone.

for x in (0..10) # rubocop:disable Style/For

Editor Integration

It's handy to view the warnings and errors produced by RuboCop as you type code in the editor instead of having to run the checks through the command line every time. Thankfully, RuboCop integration is available in most of the popular code editors and IDEs, mostly through third-party plugins. In Visual Studio Code, all you need to do is install this Ruby extension and place the following in your user settings.json file:

  "ruby.lint": {
    "rubocop": true

If you use Vim or Neovim, you can display RuboCop's diagnostics through coc.nvim. You need to install the Solargraph language server (gem install solargraph), followed by the coc-solargraph extension (:CocInstall coc-solargraph). Afterwards, configure your coc-settings.json file as shown below:

  "coc.preferences.formatOnSaveFiletypes": ["ruby"],
  "solargraph.autoformat": true,
  "solargraph.diagnostics": true,
  "solargraph.formatting": true

RuboCop integration in Neovim

Setting Up a Pre-commit Hook

A great way to ensure that all Ruby code in a project is linted and formatted properly before being checked into source control is by setting up a Git pre-commit hook that runs RuboCop on each staged file. This article will show you how to set it up with Overcommit, a tool for managing and configuring Git pre-commit hooks, but you can also integrate RuboCop with other tools if you already have an existing pre-commit workflow.

First, install Overcommit through RubyGems and then install it in your project:

$ gem install overcommit
$ overcommit --install # at the root of your project

The second command above will create a repo-specific settings file (.overcommit.yml) in the current directory and back up any existing hooks. This file extends the default configuration, so you only need to specify your configuration with respect to the defaults. For example, you may enable the RuboCop pre-commit hook through the following snippet:

# .overcommit.yml
    enabled: true
    on_warn: fail
    problem_on_unmodified_line: ignore
    command: ['bundle', 'exec', 'rubocop']

The on_warn: fail setting causes Overcommit to treat warnings as failures, while problem_on_unmodified_line: ignore causes warnings and errors on lines that were not staged to be ignored. You can browse all the available hook options and their range of acceptable values on the project's GitHub page. You may need to run overcommit --sign after changing your configuration file for the changes to take effect.

Terminal showing RuboCop pre-commit in action

Occasionally, if you want to commit a file that does not pass all the checks (such as a work-in-progress), you can skip individual checks on a case-by-case basis:

$ SKIP=RuboCop git commit -m "WIP: Unfinished work"

Adding RuboCop to Your CI Workflow

Running RuboCop checks on each pull request is another way to prevent badly formatted code from being merged into your project. Although you can set it up with any CI tool, this article will only discuss how to run RuboCop through GitHub Actions.

The first step is to create a .github/workflows directory at the root of your project and a rubocop.yml file within the new directory. Open up the file in your editor and update it as follows:

# .github/workflows/rubocop.yml
name: Lint code with RuboCop

on: [push, pull_request]

    runs-on: ${{ matrix.os }}
        os: [macos-latest, ubuntu-latest, windows-latest]

    - uses: actions/checkout@v2

    - name: Setup Ruby
      uses: ruby/setup-ruby@v1
        ruby-version: '3.0'
        bundler-cache: true

    - name: Run RuboCop
      run: bundle exec rubocop

The workflow file above describes a single job that will be executed when code is pushed to GitHub or when a pull request is made against any branch. A job is a sequence of steps that run sequentially. This particular job will run once on the latest Ubuntu, MacOS, and Windows versions provided by GitHub Actions (as defined by runs-on and strategy.matrix). The first step checks out the code in the repository, while the next one sets up the Ruby tool chain and dependencies, and the last one executes RuboCop.

Once you're done editing the file, save it, commit, and push to GitHub. Afterwards, you’ll get an inline display of any reported issues on subsequent check-ins and pull requests.

GitHub Actions failing checks

Alternative Auto-formatters

Although RuboCop provides comprehensive auto-formatting capabilities, it's also important to be aware of alternative tools in case it doesn't fulfill your needs adequately.


Prettier started out as an opinionated code formatter for JavaScript, but it now supports many other languages, including Ruby. Installing its Ruby plugin is straight forward: add the prettier gem to your Gemfile and then run bundle.

# Gemfile
gem 'prettier'

At this point, you can format your Ruby code with Prettier through the following command:

$ bundle exec rbprettier --write '**/*.rb'

Some of Prettier's rules conflict with RuboCop's, so it's necessary to disable the formatting checks of the latter so that it does not interfere with Prettier. Luckily, it's easy to turn off the RuboCop checks that conflict or are unnecessary with Prettier. All you need to do is inherit Prettier's RuboCop configuration at the top of your project's .rubocop.yml file:

# .rubocop.yml
  prettier: rubocop.yml

When you run RuboCop (with bundle exec rubocop) from now on, it won't report any layout related offenses, paving the way for Prettier to correct them according to its own rules. You can also configure Prettier's output through its configuration file, which can be shared between JavaScript and Ruby code in the same project.


RubyFmt is a brand-new code formatter that's written in Rust and currently under active development. Like Prettier, it is intended to be a formatter and not a code analysis tool. It hasn't seen a stable release just yet, so you should probably hold off on adopting it right now, but it's definitely one to keep an eye on.


Linting and auto-formatting code brings so many benefits to a code base, especially in the context of a team of developers. Even if you don't like being told how to format your code, you need to keep in mind that linting isn't just for you. It is also for the other people you collaborate with so that everyone can stick to the same conventions, thus eliminating the drawbacks of dealing with multiple coding styles in the same project.

It's also important not to treat the linter's output as gospel, so endeavor to configure it in a way that provides the most benefits to you without distracting from your main objectives. With RuboCop's extensive configuration settings, this should not be a problem. However, if you find that configuring RuboCop is taking too much time of your time, you can use a predefined style guide, as discussed earlier, or adopt Standard for a no-config alternative that everyone can just use instead of worrying about the little details.

Thanks for reading, and happy coding!

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Ayooluwa Isaiah

    Ayo is a developer with a keen interest in web tech, security and performance. He also enjoys sports, reading and photography.

    More articles by Ayooluwa Isaiah
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like:

    “Everyone is in love with Honeybadger ... the UI is spot on.”
    Molly Struve, Sr. Site Reliability Engineer, Netflix
    Start free trial
    Are you using Sentry, Rollbar, Bugsnag, or Airbrake for your monitoring? Honeybadger includes error tracking with a whole suite of amazing monitoring tools — all for probably less than you're paying now. Discover why so many companies are switching to Honeybadger here.
    Start free trial
    Stop digging through chat logs to find the bug-fix someone mentioned last month. Honeybadger's built-in issue tracker keeps discussion central to each error, so that if it pops up again you'll be able to pick up right where you left off.
    Start free trial
    “Wow — Customers are blown away that I email them so quickly after an error.”
    Chris Patton, Founder of
    Start free trial