Skip to content

Ruby code style

Marek Hulán edited this page Oct 2, 2015 · 5 revisions

Formatting

  • UTF-8 file encoding

  • Indent with 2 spaces (never use tabs!)

  • Unix style line endings

  • Spaces around operators

sum = 1 + 2
a, b = 1, 2
1 > 2 ? true : false; puts "Hi"
[1, 2, 3].each { |e| puts e }
  • No spaces after (, [ and before ], )
some(arg).other
[1, 2, 3].length
  • Use a space after { and before } as possible
[1, 2, 3].map { |number| number.upcase } # mainly in block it is for better readability
{ :number = > 1 }                        # in hashes should be used spaces
"Same #{ string }"                       # optionality to use spaces after / before
  • Indent when as deep as case. (as suggested in the Pickaxe)
case
when song.name == "Misty"
  puts "Not again!" when song.duration > 120
  puts "Too long!" when Time.now.hour > 21
  puts "It's too late"
else
  song.play
end

kind = case year
       when 1850..1889 then "Blues"
       when 1890..1909 then "Ragtime"
       when 1910..1929 then "New Orleans Jazz" when 1930..1939 then "Swing"
       when 1940..1950 then "Bebop"
       else "Jazz"
       end
  • Use an empty line before the return value of a method (unless it only has one line), and an empty line between defs.
def some_method
  do_something
  do_something_else

  result
end

def some_method
  result
end
  • Use RDoc and its conventions for API documentation. Don’t put an empty line between the comment block and the def. *Use empty lines to break up a method into logical paragraphs.
  • Keep lines fewer than 80 characters.
  • Avoid trailing whitespace.

Syntax

  • Use def with parentheses when there are arguments. Omit the parentheses when the method doesn’t accept any arguments.
def some_method
  # body omitted
 end

def some_method_with_arguments(arg1, arg2)
  # body omitted
end
  • Never use for, unless you exactly know why. Most of the time iterators should be used instead.
array = [1, 2, 3]

# bad
for element in array do
  puts element
end

# good
array.each { |element| puts element }
  • Never use then for multi-line if / unless.
# bad
if x.odd? then
  puts "odd"
end

# good
if x.odd?
  puts "odd"
end
  • Use when x; ... for one-line cases.
  • Use && / || for Boolean expressions, and / or for control flow. (Rule of thumb: If you have to use outer parentheses, you are using the wrong operators.)
  • Avoid multi-line ?: (the ternary operator), use if / unless instead.
  • Favor modifier if / unless usage when you have a single-line body.
# bad
if some_condition
  do_something
end

# good
do_something if some_condition

# another good option
some_condition && do_something
  • Favor unless over if for negative conditions:
# bad
do_something if !some_condition

# good
do_something unless some_condition

# another good option
some_condition || do_something
  • Suppress superfluous parentheses when calling methods, but keep them when calling "functions", i.e. when you use the return value in the same line.
x = Math.sin(y)
array.delete e
  • Prefer { ... } over do ... end for single-line blocks. Avoid using { ... } for multi-line blocks. Always use do ... end for "control flow" and "method definitions" (e.g. in Rakefiles and certain DSLs.) Avoid do ... end when chaining.

  • Avoid return where not required.

# bad
def some_method(some_arr)
  return some_arr.size
end

# good
def some_method(some_arr)
  some_arr.size
end
  • Avoid line continuation (\) where not required. In practice avoid using line continuations at all.
# bad
result = 1 + \
2

# good
result = 1 \
+ 2
  • Using the return value of = is okay:
if v = array.grep(/foo/) ...
  • Use ||= freely.
# set name to Bozhidar, only if it's nil or false
name ||= "Bozhidar"
  • Avoid using Perl-style global variables(like $0-9, $`, ...)

Naming

  • Use snake_case for methods and variables.
  • Use CamelCase for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.)
  • Use SCREAMING_SNAKE_CASE for other constants.
  • When defining binary operators, name the argument "other".
def +(other)
  # body omitted
end
  • Prefer map over collect, find over detect, find_all over select, size over length. This is not a hard requirement, though - if the use of the alias enhances readability - it’s ok to use it.

Comments

  • Write self documenting code and ignore the rest of this section.
  • Comments longer than a word are capitalized and use punctuation. Use two spaces after periods.
  • Avoid superfluous comments.
  • Keep existing comments up-to-date - no comment is better than an outdated comment.

Misc

  • Write ruby -w safe code.
  • Avoid hashes-as-optional-parameters. Does the method do too much?
  • Avoid long methods (longer than 10 LOC). Ideally most methods will be shorter than 5 LOC. Empty line do not contribute to the relevant LOC.
  • Avoid long parameter lists (more than 3-4 parameters).
  • Use def self.method to define singleton methods. This makes the methods more resistant to refactoring changes.
class TestClass
  # bad
  def TestClass.some_method
    # body omitted
  end

  # good
  def self.some_other_method
    # body omitted
  end
end
  • Add "global" methods to Kernel (if you have to) and make them private.
  • Avoid alias when alias_method will do.
  • Use OptionParser for parsing complex command line options and ruby -s for trivial command line options.
  • Write for Ruby 1.9. Don’t use legacy Ruby 1.8 constructs
    • use the new lambda syntax ->(x) { return x }
    • methods like inject now accept method names as arguments - [1, 2, 3].inject(&:+)
  • Avoid needless meta-programming.

Design

  • Code in a functional way, avoid mutation when it makes sense.
  • Do not mutate arguments unless that is the purpose of the method.
  • Do not mess around in core classes when writing libraries. (do not monkey patch them)
  • Do not program defensively.
  • Keep the code simple (subjective, but still ...). Each method should have a single well-defined responsibility.
  • Avoid more than 3 levels of block nesting.
  • Don’t overdesign. Overly complex solutions tend to be brittle and hard to maintain.
  • Don’t underdesign. A solution to a problem should be as simple as possible… but it should not be simpler than that. Poor initial design can lead to a lot of problems in the future.
  • Be consistent. In an ideal world - be consistent with the points listed here in this guidelines.
  • Use common sense.

Original version available at http://batsov.com/Programming/Ruby/2011/09/12/ruby-style-guide.html

Automated checks using Rubocop

For automated checks you can use excellent gem call rubocop. Install it to your project through bundler, put a provided .rubocop.yml file into the same directory and run rubocop.

Clone this wiki locally