standard

🌟 Ruby Style Guide, with linter & automatic code fixer

1877
141
Ruby

Standard - Ruby style guide, linter, and formatter

Tests
Ruby Style Guide
Gem Version

This gem is a spiritual port of StandardJS and aims
to save you (and others!) time in the same three ways:

  • No configuration. The easiest way to enforce consistent style in your
    project. Just drop it in.
  • Automatically format code. Just run standardrb --fix and say goodbye to
    messy or inconsistent code.
  • Catch style issues & programmer errors early. Save precious code review
    time by eliminating back-and-forth between reviewer & contributor.

No decisions to make. It just works. Here’s a ⚡ lightning talk
about it.

Install Standard by adding it to your Gemfile and running bundle install:

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

You can then run Standard from the command line with:

$ bundle exec standardrb

And if you’d like, Standard can autocorrect your code by tacking on a --fix
flag.

If your project uses Rake, adding require "standard/rake" adds two tasks:
standard and standard:fix. In most new projects, we tend to add the fixer
variant to our default rake task after our test command, similar to this:

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

StandardRB — The Rules

  • 2 spaces – for indentation
  • Double quotes for string literals - because pre-committing to whether
    you’ll need interpolation in a string slows people down
  • 1.9 hash syntax - When all the keys in a hash literal are symbols,
    Standard enforces Ruby 1.9’s {hash: syntax}
  • Braces for single-line blocks - Require {/} for one-line blocks, but
    allow either braces or do/end for multiline blocks. Like using do/end
    for multiline blocks? Prefer {/} when chaining? A fan of expressing intent
    with Jim Weirich’s semantic
    block

    approach? Standard lets you do you!
  • Leading dots on multi-line method chains - chosen for
    these reasons.
  • Spaces inside blocks, but not hash literals - In Ruby, the { and }
    characters do a lot of heavy lifting. To visually distinguish hash literals
    from blocks, Standard enforces that (like arrays), no leading or trailing
    spaces be added to pad hashes
  • And a good deal more

If you’re familiar with RuboCop, you
can look at Standard’s current base configuration in
config/base.yml. In lieu of a separate changelog file,
significant changes to the configuration will be documented as GitHub release
notes
.

Usage

Once you’ve installed Standard, you should be able to use the standardrb
program. The simplest use case would be checking the style of all Ruby
files in the current working directory:

$ bundle exec standardrb
standard: Use Ruby Standard Style (https://github.com/testdouble/standard)
standard: Run `standardrb --fix` to automatically fix some problems.
  /Users/code/cli.rb:31:23: Style/Semicolon: Do not use semicolons to terminate expressions.

You can optionally pass in a directory (or directories) using a glob pattern.
Be sure to quote paths containing glob patterns so that they are expanded by
standardrb instead of your shell:

$ bundle exec standardrb "lib/**/*.rb" test

Note: by default, StandardRB will look for all *.rb files (and some other
files typically associated with Ruby like *.gemspec and Gemfile)

If you want to add Standard to an existing project, but don’t want to stop all
development until you’ve fixed every violation in every file, you can create a
backlog of to-be-converted files by generating a TODO file:

$ bundle exec standardrb --generate-todo

This will create a .standard_todo.yml that lists all the files that contain
errors. When you run Standard in the future, it will ignore these files as if
they were listed under the ignore section in the .standard.yml file.

As you refactor your existing project you can remove files from the list. You
can also regenerate the TODO file at any time by re-running the above command.

Using with Rake

Standard also ships with Rake tasks. If you’re using Rails, these should
autoload and be available after installing Standard. Otherwise, just require the
tasks in your Rakefile:

require "standard/rake"

Here are the tasks bundled with Standard:

$ rake standard     # equivalent to running `standardrb`
$ rake standard:fix # equivalent to running `standardrb --fix`

You may also pass command line options to Standard’s Rake tasks by embedding
them in a STANDARDOPTS environment variable (similar to how the Minitest Rake
task accepts CLI options in TESTOPTS).

# equivalent to `standardrb --format progress`:
$ rake standard STANDARDOPTS="--format progress"

# equivalent to `standardrb lib "app/**/*"`, to lint just certain paths:
$ rake standard STANDARDOPTS="lib \"app/**/*\""

What you might do if you’re clever

If you want or need to configure Standard, there are a handful of options
available by creating a .standard.yml file in the root of your project.

Here’s an example yaml file with every option set:

fix: true               # default: false
parallel: true          # default: false
format: progress        # default: Standard::Formatter
ruby_version: 2.3.3     # default: RUBY_VERSION
default_ignores: false  # default: true

ignore:                 # default: []
  - 'db/schema.rb'
  - 'vendor/**/*'
  - 'test/**/*':
    - Layout/AlignHash

Note: If you’re running Standard in a context where your .standard.yml file
cannot be found by ascending the current working directory (i.e., against a
temporary file buffer in your editor), you can specify the config location with
--config path/to/.standard.yml. (Similarly, for the .standard_todo.yml file,
you can specify --todo path/to/.standard_todo.yml.)

What you might do if you’re REALLY clever

Because StandardRB is essentially a wrapper on top of
RuboCop, it will actually forward the
vast majority of CLI and ENV arguments to RuboCop.

You can see a list of
RuboCop’s
CLI flags here.

Why should I use Ruby Standard Style?

(This section will look
familiar

if you’ve used StandardJS.)

The beauty of Ruby Standard Style is that it’s simple. No one wants to
maintain multiple hundred-line style configuration files for every module/project
they work on. Enough of this madness!

This gem saves you (and others!) time in four ways:

  • No configuration. The easiest way to enforce consistent style in your
    project. Just drop it in.
  • Automatically format code. Just run standardrb --fix and say goodbye to
    messy or inconsistent code.
  • Catch style issues & programmer errors early. Save precious code review
    time by eliminating back-and-forth between reviewer & contributor.
  • Deliberate pace. We strive to take the hassle of upgrading Rubocop out of each
    individual team’s hands and shoulder it ourselves. We enable about ~20% of new
    cops and generally choose conservative configurations for them.

Adopting Standard style means ranking the importance of code clarity and
community conventions higher than personal style. This might not make sense for
100% of projects and development cultures, however open source can be a hostile
place for newbies. Setting up clear, automated contributor expectations makes a
project healthier.

Usage via RuboCop

If you only want to use Standard’s rules while continuing to use RuboCop’s CLI
(for example, to continue using your favorite IDE/tooling/workflow with RuboCop
support), you can configure this in your .rubocop.yml:

require: standard

inherit_gem:
  standard: config/base.yml

Who uses Ruby Standard Style?

(This section will not look very
familiar

if you’ve used StandardJS.)

If your team starts using Standard, send a pull
request
to let us
know!

Is there a readme badge?

Yes! If you use Standard in your project, you can include one of these
badges in your readme to let people know that your code is using the StandardRB
style.

Ruby Style Guide

[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)

I disagree with rule X, can you change it?

No. The whole point of Standard is to save you time by avoiding
bikeshedding
about code style. There are lots of debates online about tabs vs. spaces, etc.
that will never be resolved. These debates just distract from getting stuff
done. At the end of the day you have to ‘just pick something’, and that’s the
whole philosophy of Standard – it’s a bunch of sensible ‘just pick something’
opinions. Hopefully, users see the value in that over defending their own
opinions.

Pro tip: Just use Standard and move on. There are actual real problems that
you could spend your time solving! 😛

Is there an automatic formatter?

Yes! You can use standardrb --fix to fix most issues automatically.

standardrb --fix is built into standardrb for maximum convenience. Most
problems are fixable, but some errors must be fixed manually.

Can I override the fix: true config setting?

Also yes! You can use standardrb --no-fix. Not fixing is the default
behavior, but this flag will override the fix: true setting in your
.standard.yml config.
This is especially useful for checking your project’s compliance with
standardrb in CI environments while keeping the fix: true option enabled
locally.

How do I ignore files?

Sometimes you need to ignore additional folders or specific minified files. To
do that, add a .standard.yml file to the root of your project and specify a
list of files and globs that should be excluded:

ignore:
  - 'some/file/in/particular.rb'
  - 'a/whole/directory/**/*'

You can see the files Standard ignores by default
here

How do I hide a certain warning?

In rare cases, you’ll need to break a rule and hide the warning generated by
Standard.

Ruby Standard Style uses RuboCop
under-the-hood and you can hide warnings as you normally would if you used
RuboCop directly.

To ignore only certain rules from certain globs (not recommended, but maybe your
test suite uses a non-standardable DSL, you can specify an array of RuboCop
rules to ignore for a particular glob:

ignore:
  - 'test/**/*':
    - Layout/EndAlignment

How do I disable a warning within my source code?

You can also use special comments to disable all or certain rules within your
source code.

Given this source listing foo.rb:

baz = 42

Running standard foo.rb would fail:

foo.rb:1:1: Lint/UselessAssignment: Useless assignment to variable - `baz`.

If we wanted to make an exception, we could add the following comment:

baz = 42 # standard:disable Lint/UselessAssignment

The comment directives (both standard:disable and rubocop:disable) will
suppress the error and Standard would succeed.

If, however, you needed to disable standard for multiple lines, you could use
open and closing directives like this:

# standard:disable Layout/IndentationWidth
def foo
    123
end
# standard:enable Layout/IndentationWidth

And if you don’t know or care which rule is being violated, you can also
substitute its name for “all”. This line actually triggers three different
violations, so we can suppress them like this:

baz = ['a'].each do end # standard:disable all

How do I specify a Ruby version? What is supported?

Because Standard wraps RuboCop, they share the same runtime
requirements
—currently,
that’s MRI 2.3 and newer. While Standard can’t avoid this runtime requirement,
it does allow you to lint codebases that target Ruby versions older than 2.3 by
narrowing the ruleset somewhat.

Standard will default to telling RuboCop to target the currently running version
of Ruby (by inspecting RUBY_VERSION at runtime. But if you want to lock it
down, you can specify ruby_version in .standard.yml.

ruby_version: 1.8.7

See
testdouble/suture
for an example.

It’s a little confusing to consider, but the targeted Ruby version for linting
may or may not match the version of the runtime (suppose you’re on Ruby 2.5.1,
but your library supports Ruby 2.3.0). In this case, specify ruby_version and
you should be okay. However, note that if you target a newer Ruby version than
the runtime, RuboCop may behave in surprising or inconsistent ways.

If you are targeting a Ruby older than 2.3 and run into an issue, check out
Standard’s version-specific RuboCop
configurations
and
consider helping out by submitting a pull request if you find a rule that won’t
work for older Rubies.

How do I change the output?

Standard’s built-in formatter is intentionally minimal, printing only unfixed
failures or (when successful) printing nothing at all. If you’d like to use a
different formatter, you can specify any of RuboCop’s built-in formatters or
write your own.

For example, if you’d like to see colorful progress dots, you can either run
Standard with:

$ bundle exec standardrb --format progress
Inspecting 15 files
...............

15 files inspected, no offenses detected

Or, in your project’s .standard.yml file, specify:

format: progress

Refer to RuboCop’s documentation on
formatters
for more
information.

How do I run Standard in my editor?

It can be very handy to know about failures while editing to shorten the
feedback loop.

Language Server Protocol support

To provide immediate feedback of Standard violations and support autofixing
of your code while avoiding the performance cost of starting and stopping the
standardrb binary repeatedly, Standard Ruby ships with a built-in Language
Server Protocol
server,
which is powered by the language_server-protocol
gem
and can be
activated from the command line with the --lsp flag.

Most likely, you’d instantiate this server indirectly in your editor’s
configuration, as can be demonstrated easily with
neovim.
Theoretically, this feature could be leveraged by a purpose-built editor plugin
to performantly format and fix your code. (If you’re looking for a project, we’d
love to see one created for VS Code!)

Editor-specific guides

Why aren’t frozen_string_literal: true magic comments enforced?

Standard does not take a stance on whether you should plaster a
frozen_string_literal magic
comment

directive at the top of every file. Enforcing use of the comment became popular
when it was believed that string literals would be frozen by default in a future
version of Ruby, but according to
Matz
there are no (longer any)
such plans.

Aside from one’s personal opinion on the degree to which the comment is an
eyesore, the decision to include the magic comment at the top of every file
listing ought to be made based on the performance characteristics of each
project (e.g. whether it defines a significant number of string literals,
whether the commensurate memory usage is a material constraint, whether the code
is run as a one-off command or a long-lived server application). These tend to
indicate whether the magic comment might lead to meaningful reductions in memory
usage.

Because Standard is intended to be used as a default for every kind of Ruby
file—from shell scripts to Rails apps—it wouldn’t be appropriate for Standard to
either enforce or preclude the magic comment. Instead, you might consider
either:

  • Measuring memory performance by enabling frozen string literals as
    the default at runtime (with RUBYOPT=--enable-frozen-string-literal)
  • Introducing the
    magic_frozen_string_literal
    gem to your build, which will automatically ensure that the comment is
    prepended for every applicable file in your project

How do I use Standard with RuboCop extensions?

This is not officially supported by Standard. However, Evil Martians wrote up a
regularly updated
guide

on how to do so.

Does Standard work with [Insert other tool name here]?

Maybe! Start by searching the repository to see if there’s an existing issue
open for the tool you’re interested in. That aside, here are other known
integrations aside from editor plugins:

Contributing

Follow the steps below to setup standard locally:

$ git clone https://github.com/testdouble/standard
$ cd standard
$ gem install bundler # if working with ruby version below 2.6.0
$ bundle install
$ bundle exec rake # to run test suite

Code of Conduct

This project follows Test Double’s code of
conduct
for all community interactions,
including (but not limited to) one-on-one communications, public posts/comments,
code reviews, pull requests, and GitHub issues. If violations occur, Test Double
will take any action they deem appropriate for the infraction, up to and
including blocking a user from the organization’s repositories.