Syntax
Never use
for
, unless you know exactly why. Most of the
time iterators should be used instead.for
is implemented in terms of
each
(so you’re adding a level of indirection), but with a twist -for
doesn’t introduce a new scope (unlikeeach
) and variables defined in its
block will be visible outside it.[link]arr = [1, 2, 3]
# bad
for elem in arr do
puts elem
end
# good
arr.each { |elem| puts elem }
Prefer
{...}
overdo...end
for
single-line blocks. Avoid using{...}
for multi-line blocks (multiline
chaining is always ugly). Always usedo...end
for “control flow” and
“method definitions” (e.g. in Rakefiles and certain DSLs). Avoiddo...end
when chaining.[link]names = ["Bozhidar", "Steve", "Sarah"]
# good
names.each { |name| puts name }
# bad
names.each do |name| puts name end
# good
names.each do |name|
puts name
puts 'yay!'
end
# bad
names.each { |name|
puts name
puts 'yay!'
}
# good
names.select { |name| name.start_with?("S") }.map { |name| name.upcase }
# bad
names.select do |name|
name.start_with?("S")
end.map { |name| name.upcase }
Some will argue that multiline chaining would look okay with the use of
{...}
, but they should ask themselves if this code is really readable and
whether the block’s content can be extracted into nifty methods.Use shorthand self assignment operators
whenever applicable.[link]# 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
Avoid semicolons except for in single line class
definitions. When it is appropriate to use a semicolon, it should be
directly adjacent to the statement it terminates: there should be no
space before the semicolon.[link]# bad
puts 'foobar'; # superfluous semicolon
puts 'foo'; puts 'bar' # two expressions on the same line
# good
puts 'foobar'
puts 'foo'
puts 'bar'
puts 'foo', 'bar' # this applies to puts in particular
Use :: only to reference constants(this includes
classes and modules) and constructors (like Array() or Nokogiri::HTML()).
Do not use :: for regular method invocation.[link]# bad
SomeClass::some_method
some_object::some_method
# good
SomeClass.some_method
some_object.some_method
SomeModule::SomeClass::SOME_CONST
SomeModule::SomeClass()
Avoid
return
where not required.
[link]# bad
def some_method(some_arr)
return some_arr.size
end
# good
def some_method(some_arr)
some_arr.size
end
Don’t use the return value of
=
in
conditionals[link]# bad - shows intended use of assignment
if (v = array.grep(/foo/))
...
end
# bad
if v = array.grep(/foo/)
...
end
# good
v = array.grep(/foo/)
if v
...
end
Use
||=
freely to initialize variables.
[link]# set name to Bozhidar, only if it's nil or false
name ||= 'Bozhidar'
Don’t use
||=
to initialize boolean
variables. (Consider what would happen if the current value happened to be
false
.)[link]# bad - would set enabled to true even if it was false
enabled ||= true
# good
enabled = true if enabled.nil?
Use
.call
explicitly when calling lambdas.
[link]# bad
lambda.(x, y)
# good
lambda.call(x, y)
Avoid using Perl-style special variables (like
$0-9
,$
, etc. ). They are quite cryptic and their use in anything but
one-liner scripts is discouraged. Prefer long form versions such as
$PROGRAM_NAME
.[link]When a method block takes only one
argument, and the body consists solely of reading an attribute or calling
one method with no arguments, use the&:
shorthand.
[link]# bad
bluths.map { |bluth| bluth.occupation }
bluths.select { |bluth| bluth.blue_self? }
# good
bluths.map(&:occupation)
bluths.select(&:blue_self?)
Prefer
some_method
overself.some_method
when
calling a method on the current instance.[link]# bad
def end_date
self.start_date + self.nights
end
# good
def end_date
start_date + nights
end
In the following three common cases,
self.
is required by the language
and is good to use:- When defining a class method:
def self.some_method
. - The left hand side when calling an assignment method, including assigning
an attribute whenself
is an ActiveRecord model:self.guest = user
. - Referencing the current instance’s class:
self.class
.
When defining an object of any mutable
type meant to be a constant, make sure to callfreeze
on it. Common
examples are strings, arrays, and hashes.
([More on this][ruby-freeze].)[link]The reason is that Ruby constants are actually mutable. Calling
freeze
ensures they are not mutated and are therefore truly constant and
attempting to modify them will raise an exception. For strings, this allows
older versions of Ruby below 2.2 to intern them.# bad
class Color
RED = 'red'
BLUE = 'blue'
GREEN = 'green'
ALL_COLORS = [
RED,
BLUE,
GREEN,
]
COLOR_TO_RGB = {
RED => 0xFF0000,
BLUE => 0x0000FF,
GREEN => 0x00FF00,
}
end
# good
class Color
RED = 'red'.freeze
BLUE = 'blue'.freeze
GREEN = 'green'.freeze
ALL_COLORS = [
RED,
BLUE,
GREEN,
].freeze
COLOR_TO_RGB = {
RED => 0xFF0000,
BLUE => 0x0000FF,
GREEN => 0x00FF00,
}.freeze
end