Skip to main content

My Ruby Style

Published: Nov 24th, 2020
Updated: Dec 30th, 2020

This is part of Joyful Rails, a list of recommendations to make developing your Rails app more productive and joyful.

In this article, we are going to talk about my Ruby style.

Background

This is my Ruby style. It is not right or wrong. It is a collection of personal preferences reflecting my values and trade-offs.

Your Ruby style may be different. Decisions on coding style should reflect the environment and preferences of the people reading and writing the code.

About this article

I am going to be describing my Ruby style as a collection of configuration settings to RuboCop.

If you agree with me, you can add the settings below to your Rubocop configuration.

Use Rails cops

require: rubocop-rails

Enable new cops

New cops are added all the time and by default are pending until the next major release. Enable them automatically so you can more easily stay up to date.

AllCops:
  NewCops: enable

Global exclusion

Exclude generated files from RuboCop enforcement. I don’t write, read, or edit these files so I don’t care about their style.

AllCops:
  Exclude:
    - bin/*
    - config.ru
    - db/schema.rb
    - node_modules/**/*

Documentation

A combination of clear naming and RSpec specifications obviates the need for class documentation blocks.

Style/Documentation:
  Enabled: false

Argument Alignment

The default style, with_first_argument, wastes too much space.

method_name(:first_arg
            :second_arg)

with_fixed_indentation is great for methods with a lot of arguments.

method_with_a_long_name(:first, :second, :third,
  :forth, :fifth, :sixth, :seventh, :eigth)
Layout/ArgumentAlignment:
  EnforcedStyle: with_fixed_indentation

First Array Element Indentation

Layout/FirstArrayElementIndentation:
  EnforcedStyle: consistent

Hash Alignment

Implicit hashes do not need to be formatted like hashes.

Layout/HashAlignment:
  EnforcedLastArgumentHashStyle: ignore_implicit

Line Length

Cop directives should not need to be under our line length requirements. This makes it much easer to apply a cop directive to a single line of code.

Layout/LineLength:
  IgnoreCopDirectives: true

Allow comments to be really long. A lot of the boilerplate comments generated by Rails are over 80 characters. With this, you won’t need to fix them or delete them.

Layout/LineLength:
  IgnoredPatterns:
    - '^\s*# '

Parameter Alignment

Similar to argument alignment, the default setting with_first_parameter wastes too much space.

Layout/ParameterAlignment:
  EnforcedStyle: with_fixed_indentation

Ambiguous Block Association

Writing idiomatic RSpec requires violating this rule, so we exclude RSpec files from it.

Lint/AmbiguousBlockAssociation:
  Exclude:
    - "**/*_spec.rb"

Block Length

Idiomatic RSpec often has very long blocks. There is no harm in configuration files having long blocks. So we exclude both of those.

Metrics/BlockLength:
  Exclude:
    - Guardfile
    - config/environments/*
    - config/routes.rb
    - "**/*_spec.rb"

Method Length

It usually isn’t helpful to break up migration methods, so we allow them to get as long as they need.

Metrics/MethodLength:
  Exclude:
    - "db/migrate/*.rb"

Block Delimiters

Use doend for a multiline block, unless you are chaining.

words.each do |word|
  puts word
end

puts words.each { |word|
  word.flip.flop
}.join("\n")
Style/BlockDelimiters:
  EnforcedStyle: braces_for_chaining

Empty Method

Empty methods are unlikely to stay empty, so let’s make it easy to edit them.

def empty_method
end
Style/EmptyMethod:
  EnforcedStyle: expanded

Frozen String Literal Comment

The eventual transition to frozen string literals will not be difficult for a codebase with good specs. There is no need to clutter up our files trying to prepare for it.

Style/FrozenStringLiteralComment:
  Enabled: false

String Literals

String literals should be double-quoted when interpolated, when they include a single-quote character, or when they are natural language texts.

Natural language strings often use single quotes as apostrophes for contractions and possessives. Using double quotes means being able to change the text, including adding or removing apostrophes, without having to alter the quote characters.

For this reason, we exclude Ruby files that are likely to contain natural language text strings.

Style/StringLiterals:
  Exclude:
    - lib/tasks/*.rake
    - spec/**/*_spec.rb

Trailing Commas

Including trailing commas in arguments, array literals, and hash literals makes it easier to add, remove, and reorder items.

As a bonus, it makes it easier to read Git commits because changing one item only changes one line in the file.

Style/TrailingCommaInArguments:
  EnforcedStyleForMultiline: comma

Style/TrailingCommaInArrayLiteral:
  EnforcedStyleForMultiline: comma

Style/TrailingCommaInHashLiteral:
  EnforcedStyleForMultiline: comma