One of the open source projects Test Double maintains is called Standard Ruby. No, it’s not Ruby’s standard library and it doesn’t implement any industry standards. Instead, Standard—like the JavaScript library of the same name—is a set of static analysis (“linting”) and code style rules for your Ruby code. Because it’s built on top of RuboCop, Standard is also able to automatically lint and format your source code from the command line or even right in your editor. All that, and I haven’t even mentioned Standard’s headline feature: you can’t configure it!

And it’s a big week here at Standard HQ—we just released version 1.0.0!

It’s hard to believe that it was over two years ago when we unveiled Standard in a lightning talk at RubyConf 2018. We’ve since released over 80 iterations of the tool, incorporated dozens of rule changes from the community, and battle-tested Standard’s unconfigurable configuration against thousands of projects with over a million downloads.

As more developers have come to rely on Standard, my colleague Jennifer Konikowski has joined as a co-maintainer and helped us keep up with the steady stream of RuboCop releases (which also hit 1.0 this year!) being published by @bbatsov, @koic, and its legion of contributors. We’ve learned first-hand that staying on top of these changes is a lot of work. Because we carefully evaluate each RuboCop change before incorporating it into Standard’s base configuration, an additional value-add for our users has become apparent: Standard sweats the details of each RuboCop release, so you don’t have to!

Finally, coinciding with its 1.0 release, Standard was just added to Bundler today as one of the available options when you create a new Ruby gem project using its (excellent) bundle gem scaffolding command. (If you’ve never used bundle gem, give it a try! It makes creating a gem so easy, you’ll be publishing your own gems in no time.)

If you don’t already use Standard, it’s easy to get started. Just toss it into your Gemfile:

gem "standard"

From there, the standardrb binary will print out all of its linting and style suggestions. You can also run standardrb --fix to automatically reformat your code and get an idea on the impact adding Standard would have on your codebase.

Use Rake? Just require Standard in your Rakefile to load the standard and standard:fix tasks. For what it’s worth, I also add Standard to my default task list, as shown below:

require "standard/rake"

task default: [:test, "standard:fix"]

For more on Standard’s rules, check our README.

If you’re not already a fan of using linters and code formatters, that’s okay! One of the things that first attracted me to Ruby when I started using it in 2005 was how free-form and liberating it was in comparison to Java. As a result, any tool that constrains Ruby’s expressiveness risks undercutting one of the best reasons to use Ruby in the first place!

It’s for this reason we’re incredibly conservative about the rules we’ve chosen to enable in Standard. Here are some of our guiding principles, and how they might benefit your project:

  • Catch automatically-detectable bugs early. The single most important role of a linter is to catch avoidable bugs as soon as possible, often no later than when the file is saved (as opposed to in a test, during a CI run, or in production). RuboCop contains a massive number of these rules and Standard enables the vast majority of them

  • Increase consistency around things that don’t matter. For example, Standard requires all string literals be double-quoted. Single-quotes don’t support interpolation but aren’t any more performant, so mixing single & double quoted strings adds a bit of cognitive overhead with zero discernible benefit

  • Reduce version control churn. Standard enforces some basic layout rules: a single blank line between methods, one level of indentation for multi-line statements, no trailing whitespace, etc. The primary benefit of these rules is to cut down on the incidental layout changes accompanying meaningful changes to your code’s behavior. Once you’ve adopted Standard, your team’s git diffs will be laser-focused on your code’s actual behavior, not its formatting

Standard is essentially a thin candy shell on top of RuboCop. We built it that way because RuboCop is a great tool in its own right! Rather than compete with RuboCop, Standard aims to leverage its breadth of technical capabilities in order to establish a set of community norms among as many Ruby developers and codebases as possible. Ruby’s expressiveness is one of its greatest strengths, but that same flexibility can lead to Balkanization within our community when different projects arrive at wildly different style rules, and Standard seeks to address that.

  • Eliminate bikeshedding. When a team adopts a highly-configurable tool like RuboCop in an effort to normalize on code style, it creates a new problem: agreeing on how to configure it. On some teams, certain members can be domineering: using tools like RuboCop to impose their will on others with draconian configuration choices—resulting in their teammates losing their own sense of agency in their work. On other teams, the incorporation of a linter doesn’t actually settle any code style debates, it just shifts the field of battle from the code itself to a configuration file. Energy spent on your team debating the merits of whether multi-line method chains should have leading dots or trailing dots could probably be better spent elsewhere; that’s why Standard already had that debate once and for all. (For the record, I lost that argument—but I still use Standard anyway!)

  • Consistency across projects. Some large organizations will maintain a single RuboCop configuration and promulgate it across all their repositories. Standard essentially accomplishes the same thing, except it’s intended for use by the entire Ruby community. When you switch from one Standard Ruby project to another, a substantial amount of friction is eliminated. You no longer need to exert any mental energy to think about how to adjust your code style to adhere to the conventions of that particular project. And as Standard is adopted by more open source projects, if you start using Standard at work you’ll effectively reduce the barrier-of-entry for your teammates to contribute back to open source, too!

If your team uses RuboCop today and things are going well, by all means do what works for you! But if you can get behind the idea that increased consistency across Ruby projects would be a net good for our community, I hope you’ll consider giving Standard a second look!

Not many of my projects ever reach 1.0. But with Standard, we wanted to communicate that things are pretty much stable and won’t be changing dramatically from here on out. That said, the work is hardly over. RuboCop continues to be one of the most prolific gems in the Ruby ecosystem, releasing on a nearly biweekly cadence. And Ruby itself is no slouch either; many of us doubted Matz’s promises for Ruby 3.0 back in 2015, but amazingly almost all of them came true! Our commitment is to continue the work of maintaining Standard as Ruby and Rubocop change and evolve, and we’ll continue to invest in better integrations with developer tools like editors and CI/CD environments.

If you’ve been holding out on trying Standard, waiting for the dust to settle, now’s a great time to start using it. And if you find something you don’t like, we still want to hear from you! Just open an issue or tweet at us.

Justin Searls

Hash An icon of a hash sign Code Name
Agent 002
Location An icon of a map marker Location
Columbus, OH