CLI tool
rubocop/rubocop-rails avatar
rubocop/rubocop-rails

rubocop-rails: linting that knows what a Rails application looks like

A RuboCop extension focused on enforcing Rails best practices and coding conventions.

877 stars320 forksRubyMIT

At a glance

What is it?
rubocop-rails is a RuboCop plugin that adds cops for Rails specific practices, from finding records by id to schema checks in migrations, with configuration for the Rails version and the migrated schema. It suits a Rails team that wants its house style enforced by the linter rather than by a review checklist.
Who is it for?
rubocop-rails is a good fit for a Rails team that already runs RuboCop and wants the Rails-specific checks turned on, because the plugin gives you a maintained set of cops rather than a hand-written list of exclusions, and it lets you point the linter at the right Rails version so the version-specific rules are correct.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It is a plugin, and loading it is a one-line change

The extension is loaded through the RuboCop plugin system, and the readme is explicit that this repository manages the rubocop-rails gem from version 2.0.0 onwards, with the older gem at 1.5.0 and below having been renamed to a separate configuration gem. That note matters if you are upgrading from a long-lived project, because the gem name changed and the old one is now something else. Installation is the usual gem install:

sh
$ gem install rubocop-rails

Or, with Bundler, a line in the Gemfile:

ruby
gem 'rubocop-rails', require: false

The require false is deliberate, since the plugin is loaded by RuboCop itself rather than by your application. Three ways of telling RuboCop to load it are given. In the configuration file you put a plugins key, and there is an array form for when you have several extensions:

yaml
plugins:
  - rubocop-other-extension
  - rubocop-rails

The command line form is a single flag, and the Rake task form sets the plugins list on the task object. There is a version caveat attached to the plugin system, which is supported in RuboCop 1.72 and newer, with earlier versions using require instead. Once loaded, running RuboCop picks up the Rails cops alongside the standard ones.

TargetRailsVersion, and why the linter needs to know

The first Rails specific setting is the one that decides which rules apply. The TargetRailsVersion option under AllCops asks what version of Rails the inspected code is using, and the acceptable values are given as a float such as 7.2, with the note that the patch version should not be included. If the option is not set, RuboCop parses the Gemfile.lock or the gems.locked file to find the bound version of Rails, and if neither file exists it falls back to Rails 5.0. That fallback is worth knowing about, because a project with no lock file will silently get the rules for a Rails version that may be several major versions behind the one in use. Setting the option explicitly removes the ambiguity, and the readme treats it as a supported value rather than a hint, which is the right way round since a linter rule that depends on a version is only correct relative to a version.

MigratedSchemaVersion, the setting that stops your migrations being flagged

The second setting is the more interesting one and it exists to solve a specific annoyance. By specifying MigratedSchemaVersion, migration files that have already been run can be ignored, and files lower than or equal to the given value are skipped. The example given sets a timestamp and explains that this is how you would ignore a particular create articles migration and the ones before it:

yaml
AllCops:
  MigratedSchemaVersion: '20241225000000'

The effect is that the linter stops inspecting schema settings in already applied migration files. The reason is stated plainly, that changing already applied migrations should be avoided because it can lead to the schema getting out of sync between your local copy and what it actually is in production, depending on when the migrate command was run. The guidance for anyone who wants to change their schema to satisfy the cops is to create new migrations instead. In other words, the setting is not a suppression of a false positive but a way of telling the linter which part of the migration history is history, and the default behaviour of flagging them is the reminder that the migration files and the live schema have to agree.

Autocorrecting generated code, and the unsafe flag question

There is a configuration tip that most Rails projects end up wanting, and it comes with a caveat you should read. In Rails 6.1 and later, you add a setting to the development environment file so that RuboCop autocorrection is applied to the code that the generator produces:

ruby
Rails.application.configure do
  config.generators.after_generate do |files|
    parsable_files = files.filter { |file| file.end_with?('.rb') }
    unless parsable_files.empty?
      system("bundle exec rubocop -A --fail-level=E #{parsable_files.shelljoin}", exception: true)
    end
  end
end

The mechanism uses the unsafe autocorrect flag to apply the frozen string literal comment cop and other unsafe correction cops. The readme is careful about why, noting that the flag is unsafe autocorrection but that code generated by default is simple and less likely to be incompatible with it, and that you can fall back to the safe flag if you hit problems. In Rails 7.2 and later there is a one-line alternative, the apply autocorrect after generate configuration, which the readme says is the recommended route and which you only need to uncomment.

The cops themselves, and how to tune one

The cops live under a single directory in the library, and each one comes with its own examples and documentation, which is the format the RuboCop project expects. From the configuration side they are treated exactly like any other cop, with the same per-cop configuration block, so excluding a file or a directory works the way you would expect. The example given uses the find by cop, which is one of the more valuable ones in a Rails codebase, since a call that looks a record up by its primary key rather than by some other field is exactly the kind of thing that quietly becomes an N plus one query. The documentation link is to the official RuboCop Rails documentation, and the compatibility section states that the Rails cops support Rails 4.2 and newer, which is a wide range and means the cops are written to degrade rather than to assume a recent version. The repository also carries a configuration directory for the default settings, a changelog directory with per-release notes, a relnotes directory, and a rubocop_todo file, which is where a large project records the offences it has decided to live with for now.

Editorial conclusion

rubocop-rails is a good fit for a Rails team that already runs RuboCop and wants the Rails-specific checks turned on, because the plugin gives you a maintained set of cops rather than a hand-written list of exclusions, and it lets you point the linter at the right Rails version so the version-specific rules are correct. It is the wrong choice if your project does not use Rails, since the cops are written against Rails idioms, and it is the wrong choice if you only need a couple of checks, since RuboCop itself covers the general Ruby style. It is also the wrong choice if you want the linter to rewrite your migrations, because the configuration is designed to skip migrations that have already run. Before adopting it, check the compatibility list, which covers Rails 4.2 and newer, and read the configuration for the migrated schema version, because leaving it unset means already applied migrations will be inspected and flagged. The project is MIT licensed, the last push was on 2026-10-15, and the current release is v2.38.0 from 2026-09-20.

Frequently asked questions

What is rubocop-rails?

It is a RuboCop extension focused on enforcing Rails best practices and coding conventions, adding cops for Rails specific patterns on top of the standard RuboCop checks. The cops live under a single directory in the library and each one ships with its own examples and documentation.

How do I load the rubocop-rails extension?

Install the gem, then tell RuboCop to load the plugin, either with a plugins key in the .rubocop.yml file, with the --plugin command line flag, or by setting the plugins list on a Rake task. The plugin system requires RuboCop 1.72 or newer, and earlier versions use require instead.

What does the TargetRailsVersion option do?

It states which version of Rails the inspected code uses, given as a float such as 7.2 without the patch version. If it is not set, RuboCop parses the Gemfile.lock or the gems.locked file to find the bound version, and falls back to Rails 5.0 if neither file exists.

What does MigratedSchemaVersion do in rubocop-rails?

It lets you ignore migration files that have already been run, with files lower than or equal to the given value skipped. This prevents the linter from inspecting schema settings in applied migrations, since changing them can leave your local copy out of sync with production, and the guidance is to create new migrations instead.

Which Rails versions does rubocop-rails support?

The compatibility section states that the Rails cops support Rails 4.2 and newer. The project is MIT licensed, the current release is v2.38.0 from 2026-09-20, and the last push was on 2026-10-15.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. rubocop/rubocop-rails on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rubocop-rubocop-rails.svg)](https://hysenlabs.com/projects/rubocop-rubocop-rails)

Was this useful?