Ruby Style Guide

A Ruby-specific style guide designed to help your code look and perform better.

Scroll down...

Content

Resources

Comments

There are some styles which are specific to Ruby that you should understand if you want to produce legible and effective code.

In the end, it often matters more that you produce legible code than that you've managed to cram everything you're trying to do into 3 lines. Someone has to read this after you (maybe even you later).

The goal for this lesson isn't to get you to memorize all this -- just browse through it to pick up some style pointers now and come back to it later when you're ready to brush up.

See this Ruby style guide from Github or this open-source one if you're looking for truly comprehensive style information. The most important items are listed below.

General Things

Use 2 Spaces for Indentation

# 2 spaces better than 4.  Never tabs.
def two_spaces
  puts "2 spaces: good!"
end
def four_spaces
    puts "not so good..."
end
def tab
     puts "do NOT use tabs"
end

Space Things Out

# around operators
sum = 1 + 2

# after commas
a, b = 1, 2 

# after just about everything...
[1, 2, 3].each { |e| puts e } # 
class FooError < StandardError; end
{ :item1 => "val1", :item2 => "val2" }

Align Descendent Lines

result = if some_cond
           calc_something
         else
           calc_something_else
         end

menu_item = [
  'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam',
  'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'
]

Align Multi-Line Parameters or Arguments

some_hash = { :thing1 => val1,
              :thing2 => val2,
              :thing3 => val3 }
def send_mail(source)
  Mailer.deliver(to: 'bob@example.com',
                 from: 'us@example.com',
                 subject: 'Important message',
                 body: source.text)
end

Underscore Long Numeric Literals

The underscore is for human readability, it's ignored by the number.

num = 1_000_000

Limit Lines to 80 Characters

Or even 70 characters. This includes comments.

# I am a very long comment and because of that you
# want to make it multiple lines long.  That's
# important because otherwise no one will see it and
# they will think you're a total amateur.

Avoid Trailing Whitespace

There are add-ons which highlight or automatically remove trailing whitespaces from your lines. It's considered bad style to have lots of unnecessary spaces at the end of lines.

Strings

Prefer Interpolation

# bad
email_with_name = user.name + ' <' + user.email + '>'

# good
email_with_name = "#{ user.name } <#{ user.email }>"

Collections

Prefer Literal Array and Hash Creation Notation

# bad
arr = Array.new
hash = Hash.new

# good
arr = []
hash = {}

Use %w For Literal Array Creation

# bad
STATES = ['draft', 'open', 'closed']

# good
STATES = %w(draft open closed)

Prefer Symbols Instead of Strings in Hash Keys

# bad
hash = { 'one' => 1, 'two' => 2, 'three' => 3 }

# good
hash = { one: 1, two: 2, three: 3 }

Don't Modify a Collection While Traversing It

# bad
[1,2,3].each_with_index do |num, i|
  self[i+1] = self[i]
end

Conditionals

Don't use For Loops

...unless you know exactly why. Ruby has lots of iterators that are more appropriate and faster.

Don't be Scared of the Ternary Operator

...but don't use it for nested or very long ifs.

# bad
result = if some_condition then something else something_else end

# good
result = some_condition ? something : something_else

Use ! Instead of Not

# bad - braces are required because of op precedence
x = (not something)

# good
x = !something

Use && and || Instead of "And" and "Or"

true && false
false || true

Utilize Single-Line If or Unless

# bad
if some_condition
  do_something
end

# bad
unless some_condition
  do_something
end

# good
do_something if some_condition

# good
do_something unless some_condition

Don't Be Afraid of Unless

# bad
do_something if !some_condition

# bad
do_something if not some_condition

# good
do_something unless some_condition

# another good (and sneaky) option
some_condition || do_something

Looping

Don't Be Afraid of Until

# bad
do_something while !some_condition

# good
do_something until some_condition

Use Single-Line While or Until

# bad
while some_condition
  do_something
end

# good
do_something while some_condition

Use Next In Loops Instead of Conditionals

# bad
[0, 1, 2, 3].each do |item|
  if item > 1
    puts item
  end
end

# good
[0, 1, 2, 3].each do |item|
  next unless item > 1
  puts item
end

Methods and Blocks

Keep Methods Short

Methods should be < 10 lines of code (empty lines not counted).

Keep Methods Tight

Avoid long lists of parameters -- is your method doing too much?

Use Parentheses Around Method Arguments

...unless they are top level methods like attr_accessor

class Person
  attr_reader :name, :age

  def some_method(arg1, arg2)
  end
end

Use Appropriate Block Syntax

If it's short, put it on one line.

names = ['Bozhidar', 'Steve', 'Sarah']

# bad
names.each do |name|
  puts name
end

# good
names.each { |name| puts name }

# bad
names.select do |name|
  name.start_with?('S')
end.map { |name| name.upcase }

# good
names.select { |name| name.start_with?('S') }.map { |name| name.upcase }

Avoid Return or Self When Not Needed

Use implicit returns and implicit self.

# bad
def some_method(some_arr)
  self.do_something if self.some_attr
  return some_arr.size
end

# good
def some_method(some_arr)
  do_something if some_attr
  some_arr.size
end

Operations

Use Shorthand Operators

# bad
x = x + y
x = x * y
x = x**y
x = x / y
x = x || y
x = x && y

# good
x += y
x *= y
x **= y
x /= y
x ||= y
x &&= y

Use Ruby's Syntactic Sugar Methods

# bad
if x % 2 == 0
end

if x % 2 == 1
end

if x == nil
end

# good
if x.even?
end

if x.odd?
end

if x.nil?
end

Classes

Supply Classes with a To_s Method

... if they represent proper objects. You will likely need to print instances out so Ruby needs to know how to print them.

class Person
  attr_reader :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end

  def to_s
    "#{@first_name} #{@last_name}"
  end
end

Keep a Single Class or Module Per File

The name of the file should be named after that class/module.

# human.rb
class Human
end

Naming

Use SCREAMING_SNAKE_CASE for Constants

SOME_CONST = 42

Use CamelCase for Classes and Modules

class SomeClass
end

module SomeModule
end

Use snake_case for Everything Else

some_variable

def some_method
end

"some_file.rb"

:some_symbol

Keep Acronyms Uppercase

def XML_parser
end

Use Bangs! For Hazardous Methods

def modifies_arr!(arr)
  # code to modify arr
end

Commenting

  • Leave a space between the # and the start of the comment
  • Don't comment self-explanatory code
  • use TODO to denote upcoming features
  • Don't forget to stick to 80 lines and use multi-line comments if necessary!

See this post from Ben Orenstein for particulars.

Exceptions

Don't Use Exceptions for Flow Control

# bad
begin
  n / d
rescue ZeroDivisionError
  puts 'Cannot divide by 0!'
end

# good
if d.zero?
  puts 'Cannot divide by 0!'
else
  n / d
end


Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

There are no additional resources for this lesson just yet!

Sorry, comments aren't active just yet!

Next Lesson: Test Yourself: Ruby Inheritance