SVG RuboCop Logo, Copyright (c) 2014 Dimiter Petrov, CC BY-NC 4.0, see docs/images/logo/README.txt Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5, see docs/images/logo/README.txt SemVer.org Logo by @maxhaz, see docs/images/logo/README.txt

RuboCop LTS - Rules for Rubies: Rubocop + Standard + Betterlint + Shopify + Gradual

💡 See the intro blog post!


The RuboCop LTS family of gems is the distillation of almost 20 years of my own Ruby expertise and source code diving, built on the shoulders of the expertise of many others; organizing that expertise into per-Ruby-version sets of configurations.

Although the situation has improved somewhat, it remains unsafe to upgrade RuboCop, or Standard, in a project that supports EOL Rubies.

I hope it helps others avoid some of the challenges I’ve had with library maintenance, and supporting decade-old mission-critical applications.

Avoid bike-shedding, use rubocop-lts in every project, and let it manage your linting complexity!

If the rubocop-lts stack of libraries has helped you, or your organization, please support my efforts by making a donation, or becoming a sponsor.

[![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] Buy me coffee donation button Patreon donate button

Why Build This?

⁉️ What about Standard? It provides ruby-version-specific RuboCop rules, doesn’t it?

Actually, not in the sense you might have assumed if you are asking that question.

I assumed as much when I first became aware of the discrete configs for specific versions of Ruby via Evil Martians’ write ups (here (rubocop + standard), and here (adds rubocop-gradual)). However, the discrete configs, which go all the way back to Ruby 1.8, are not intended to keep a code base “compatible” with the specified version of Ruby. According to Justin Searls, the project’s author and lead maintainer, Standard’s ruby-specific configs merely disable rules where keeping Standard’s more modern style would “break” the older Ruby.

In other words, they do not attempt to actively ensure compliance with any older Ruby syntax, even when that is possible, and advisable, for a project targeting long-term support of older Ruby versions.

For example standard does not:

  • set Layout/DotPosition to EnforcedStyle: trailing for Ruby 1.8 compatibility, nor does it
  • set Style/SymbolArray and Style/WordArray to EnforcedStyle: brackets for Ruby 1.8 and 1.9 compatibility.

Instead, these style enforcers are completely disabled.

This is why you need rubocop-lts. It is built on top of standard-rubocop-lts, which shims standard’s rules to enforce maximum compatibility for targeted versions of Old Ruby.

You get the standard rules as much as possible, but without breaking your old Ruby compatibility.

Also, I’ve added a bunch of other linter rules on top of Standard, e.g. Shopify’s rules.

This is still an anti-bike-shedding tool, but my goal is not to have fewer rules. My goal is to be able to integrate this tool with a code base, on any version of Ruby, in as few lines as possible.

🙋‍♀️ How often has RuboCop broken your build?

This is both good (literally its job) and bad (when it’s for the wrong reasons).

It’s supposed to break the build when it finds violations. It should not break the build due to incompatibility with your environment. RuboCop doesn’t exactly follow SemVer, and occasionally it will unexpectedly break things.

Here’s a recent example of a scenario that could have been avoided, and from now on will be!