Ruby Style Guidelines

Style

Limit lines to 80 characters. Never leave trailing whitespace. End each file with a newline. Avoid more than three levels of block nesting.

Indentation

Use two spaces per level of indentation. No hard tabs.

def some_method
    do_something
  end

For case statements, ‘when’ should align with ‘case’.

case
when thing == 'thing'
  do_something
when thing == 'other thing'
  do_something_else
else
  do_something_completely_different
end

When assigning with a case statement, everything should be indented and aligned.

thing =
  case foo
  when foo then 'bar'
  when bar then 'foo'
  else 'baz'
  end

thing =
  if foo
    'bar'
  else
    'baz'
  end

Line format

Use new lines per expressions or statements, do not use ;.

# bad
puts 'foo'; puts 'bar'

# good
puts 'foo'
puts 'bar'

Use an empty line between methods.

def some_method
  do_something
end

def some_method
  do_something
end

Use an empty line to break methods into logical sections.

def some_method
  data = initialize

  data.do_something

  data.result
end

Use lines to separate long list of parameters.

# bad
def send_mail(source)
  Mailer.deliver(to: 'email@example.com', from: 'another@example.com', subject: 'Some title', body: "foo bar baz")
end

# good
def send_mail(source)
  Mailer.deliver(
    to: 'email@example.com',
    from: 'another@example.com',
    subject: 'Some title',
    body: "foo bar baz"
  )
end

Align array elements over multiple lines.

# bad
menu_item = ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo',
  'Foo', 'Foo', 'Foo', 'Foo', 'Foo']

# good
menu_item = [
  'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo',
  'Foo', 'Foo', 'Foo', 'Foo', 'Foo'
]

Use single line format for empty class definitions.

# bad
class Suprise < StandardError
end

# good
class Suprise < StandardError; end

# good
Suprise = Class.new(StandardError)

Use multi line format for methods.

# bad
def some_method; do_something; end

# good
def some_method
  do_something
end

Whitespace

Use white space to make your code more readable.

thing = 1 + 4 - 10
a, b, c, d
[1, 2, 3].each { | k, v | puts v if k == 10 }
"interpolate #{ this }"

There are a few exceptions where you cannot use whitespace as it will cause an error.

some_method(argument)
["some", "array"].first
!something

Syntax

Use :: only to reference constants and constructors, not for regular method invocation.

FooClass.some_method
foo_object.some_method
BareModule::FooClass::CONSTANT
BarModule::FooClass

Only use parentheses on methods that accept parameters.

def some_method
  body
end

def some_method(arg1, arg2)
  body
end

Use the each method in favour of the for method.

# bad
for element in array do
  puts element
end

# good
array.each { |element| puts element }

When it is readable and not multiline, favour the ternary opertor over an if statment.

# bad
thing = if foo == bar then do_something else do_something_else end

# good
thing = foo == bar ? do_something : do_something_else

Unless it is a single conditional.

do_something if foo == bar

Do not use !! to check if a value is nil, instead use .nil?.

# bad
if !!foo

# good
unless foo.nil?

Use operators, not keywords.

and   # bad
&&    # good

or    # bad
||    # good

not   # bad
!     # good

Don’t use double negatives.

if !condition     # bad
unless condition  # good

while !condition  # bad
until condition   # good

Omit the outer braces around an implicit options hash.

# bad
user.set({ name: 'admin',  authorization: { read: true, write: true } })

# good
user.set(name: 'admin',  authorization: { read: true, write: true })

Use { } for single-line blocks.

# bad
things.each do |thing|
  puts thing
end

# good
things.each { |thing| puts thing }

Avoid return where not required.

# bad
def some_method
  return something
end

# good
def some_method
  something
end

Use shorthand self assignment operators whenever applicable.

# bad
x = x + y     is the same as     x += y
x = x * y     is the same as     x *= y
x = x**y      is the same as     x **= y
x = x / y     is the same as     x /= y
x = x && y    is the same as     x &&= y
Use   = when you want to initialise variables only if they’re not already initialised.
foo ||= 'bar'

Use &&= to preprocess variables that may or may not exist.

# bad
if something
  something = something.downcase
end

# good
something &&= something.downcase

Use the new lambda literal syntax for single line body blocks.

l = ->(x, y) { x = y }

Use the lambda method for multi-line blocks.

l = lambda do |x, y|
  foo = y
  bar = x
end

Prefer proc over Proc.new.

# bad
p = Proc.new { |n| puts n }
p.()

# good
p = proc { |n| puts n }
p.call()

Favour the use of predicate methods to explicit comparisons.

x.even?
x.odd?
x.nil?
x.zero?

Classes

Avoid self where not required. It is only required when calling a self write accessor.

Use a consistent structured order in classes.

  1. extend and include
  2. constants
  3. attribute macros
  4. other macros
  5. public class methods
  6. public instance methods
  7. protected methods
  8. private methods

Prefer modules to classes with only class methods. Classes should be used only when it makes sense to create instances out of them.

# bad
class SomeClass
  def self.some_method
    do_something
  end

  def self.some_other_method
  end
end

# good
module SomeClass

  def some_method
    do_something
  end

  def some_other_method
  end
end

Use attr functions to define accessors.

class Foo
  attr_reader :bar, :baz
end

Avoid the usage of class variables. It will cause unexpected results with inheritance. Class instance variables should usually be preferred over class variables.

Assign proper visibility levels to methods (private, protected) in accordance with their intended usage.

class FooClass
  def public_method
    do_something
  end

  private

  def private_method
    do_something
  end
end

Use def self.method to define singleton methods.

class FooClass
  def self.some_method
    do_something
  end
end

Or if you have multiple.

class FooClass

  module ClassMethods
    def some_method
      do_something
    end

    def other_method
      do_something
    end
  end

end

Methods

Avoid hashes as optional parameters. Does the method do too much? Object initialisers are exceptions for this rule. Ideally, most methods will be shorter than 5 lines. Empty lines do not contribute to this.

Arrays and Hashes

Prefer literal array and hash creation notation.

arr = []
hash = {}

Prefer %w for strings, or %i for symbols to the literal array syntax.

things = %w(draft open closed)
things = %i(draft open closed)

Prefer symbols instead of strings as hash keys.

hash = { foo: 1, bar: 2, baz: 3 }

Strings

Use string interpolation rather than string concatenation.

# bad
foo = bar.baz + ', ' + bar.qux

# good
foo = "#{ bar.baz }, #{ bar.qux }"

Prefer double-quotes unless your string literal contains “ or escape characters you want to suppress.

foo = "Bar"

Exceptions

Don’t use exceptions to control flow.

# bad
begin
  foo / bar
rescue ZeroDivisionError
  "Can't do this"
end

# good
if foo.zero?
  "Can't do this"
else
  foo / bar
end

Use raise only when catching an exception and re-raising it.

begin
  fail 'BAD'
rescue => error
  raise if error.message != 'BAD'
end

Supply an exception class and a message as two separate arguments.

# bad
fail SomeException.new('message')

# good
fail SomeException, 'message'

Use implicit begin blocks where possible.

# bad
def foo
  begin
    # main logic goes here
  rescue
    # failure handling goes here
  end
end

# good
def foo
  # main logic goes here
rescue
  # failure handling goes here
end

Naming

Name identifiers in English. Use snake_case for naming files and directories. Use snake_case for symbols, methods and variables and constants.

:some_symbol

def some_method
  ...
end

SOME_CONSTANT = nil

Use CamelCase for classes and modules.

class SomeClass
  ...
end

Methods that return a boolean value should end in a question mark.

class boolean_method?
  ...
end

Methods which overwrite a value should end with a bang if there is a non bang version available.

class Foo
  def bar!
  end

  def bar
  end
end

Commenting

Good code is its own best documentation. As you’re about to add a comment, ask yourself, “How can I improve the code so that this comment isn’t needed?” Improve the code and then document it to make it even clearer. – Steve McConnell

Keep comments up to date. Don’t use block comments. They cannot be preceded by whitespace and are not as easy to spot as regular comments.

# bad
=begin
comment line
another comment line
=end

# good
# comment line
# another comment line