Limit lines to 80 characters. Never leave trailing whitespace. End each file with a newline. Avoid more than three levels of block nesting.
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
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
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
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?
Avoid self where not required. It is only required when calling a self write accessor.
Use a consistent structured order in classes.
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
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.
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 }
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"
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
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
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