Article

Elements of Ruby Style

Noel Rappin

This post was previously on the Pathfinder Software site. Pathfinder Software changed its name to Orthogonal in 2016. Read more.


Next week marks the publication of the 50th Anniversary edition of the Strunk & White’s The Elements of Style, a critically important work for anybody who puts words together on a regular basis.

In that spirit, here are some thoughts on good Ruby & Rails style — I’m mostly focusing on Ruby-specific guidelines here. This is somewhat closer to a brain dump than a fully-baked style guide, so it’s something I intend to come back to, especially after hearing everybody tell me exactly where I’m wrong, wrong, wrong.

UPDATE: There were some comments about the formatting being messed up. Apparently, whatever tool we’re using for code coloring doesn’t work well with Safari. In Firefox, the formatting is as intended. We’ve cleaned this up — thanks for your patience.

The goals of well-styled code are correctness and simplicity, in that order.

I don’t want to pretend that it’s not important for code to be correct. Still, I think that functionally correct code is not the last step. For me, the best order is: Make it Work, Make it Clean, Make it Fast (if necessary).

Ruby code should be indented two spaces.

This should be uncontroversial, right? Indenting Ruby code four spaces indicates that you are a very recent convert from Java.

I also think that ERb and HTML within ERb should be indented two spaces. Indentation inside an ERb Ruby block should be aligned with the ERb delimeter, not the the Ruby statement, so this:

<% if something %>
  two spaces
<% end %>

Not this:

<% if something %>
     too many spaces
<% end %>

Statements that extend past 80 characters or so should be broken up and indented on the following line.

This one may be a little idiosyncratic, since I tend to use a narrower edit window than a lot of people. That said, it’s still a good idea to have a hard right margin to your code. Whether it’s 80 or 100 characters is less relevant than that all of the code can fit on the screen without scrolling. If you have to scroll to see code, eventually, you’ll make mistakes based on code that you can’t all see at once. (I find this especially true in HTML/ERb, where you can easily mangle a closing tag in column 125 and lose your mind trying to find the problem).

There are two possibilities for indenting the second part of a long line. The first, which is the one recommended in Code Complete, is to double indent it compared to the top line:

a_very_long_method_name(argument1,
    a + b, arg 3)

The other is to indent to the level of the parenthesis in the statement, like Emacs Lisp does:

a_very_long_method_name(argument1,
                        a + b, arg 3)

In either case, you should never break up individual sub statements — in the above examples, never split up a + b — you should try to keep entire expression, hash or array arguments on the same line even if that means the line above is shorter.

Anyway, both choices have tradeoffs. The double-indent is the easiest to maintain as the code changes but can make it tricky to follow the logical structure of the code. The longer indent makes it generally clear what goes together, but it’s a little hard to keep up, and can look kind of ragged.

I tend to prefer the first form for Ruby, although I do use the second sometimes, especially for, say, hash options inside a larger statement.

Ruby allows you to leave out parenthesis, in general, resist this temptation.

Parenthesis make the code easier to follow. General Ruby style is to use them, except in the following cases:

  • Always leave out empty parentheses
  • The parentheses can be left out of a single command that is surrounded by ERb delimiters — the ERb markers make sure the code is still readable
  • A line that is a single command and a single simple argument can be written without the parenthesis. Personally, I find that I do this less and less, but it’s still perfectly readable. I tend not to like single lines in regular ruby code that have multiple arguments and no parentheses.
  • A lot of Ruby-based Domain Specific Languages (such as Rake) don’t use parenthesis to preserve a more natural language feel to their statements.

Use if statements as expressions.

Not this — it’s overlong, kind of redundant, and not in the spirit of Ruby as I understand it:

if boolean
  x = 3
else
  x = 5
end

But this:

x = if boolean then 3 else 5 end

I prefer the use of the explicit if statement to the ternary operator. In the case where the if statement becomes too long to fit on one line, I tend to indent to the level of the if statement:

x = if boolean
    then 3
    else 5
    end

I also tend to keep the then in the line, although it’s technically not needed.

Use of Ruby idioms

There are a couple of idioms that, although they are sort of opaque the first time you see them, are commonly used enough that they should be used in place of wordier alternatives. Right now the list starts at three:

||= as in, @user ||= User.find(params[:id])

&&= as in, @user.name &&= @user.name.downcase

Symbol#to_proc as in, array.map(&:upcase)

I realize some people don’t like Symbol#to_proc — I really do, though.

Only use trailing if statements in guard clauses.

Ruby lets you write statements that are only executed conditionally UPDATED for syntactic correctness

return if x.nil?

In general, these statements can get hard to read (people tend to overlook the if part) and should only be used if:

  • The statement and the conditional are both simple
  • The statement is a guard clause that prevents execution of the rest of the method — this can save a level of indent and make the method easier to read

Multiple return statements are fine. But in Ruby, you can leave off the last one.

You will sometimes read people who say that a method should only have one return statement. I disagree with that — I’d rather get out of the method early if the data is wrong then have the guts of the method indented inside an if statement.

In Ruby, every method returns the value of its last expression, so you only need to explicitly include a return statement when you are bailing out of a method. That’s a useful enough distinction that I don’t use the actual return statement on the last line of code even if it’s a simple statement of the return value.

Block Layout

The convention is braces for single line blocks and do/end for multi-line blocks:

list.map { |x| x + 3 }

list.map do |x|
  x + 3
end

I’m okay with using braces for a multi-line block if you are using the result of the entire statement in a chain (but see below):

list.map { |x|
  x + 3
}.sort

Stringing things together

Ruby tends to encourage stringing method results together, especially for a bunch of enumeration methods:

all_users.select(&:is_active).map(&:name).sort

Although you can go overboard with this, I think it’s okay as long as the logical chain makes sense as a single operation — I’d avoid it if it was genuinely chaining through a series of different objects (I probably would avoid doing something like user.manager.company.name.size as a single line).

Anyway, if this goes over a single line, that’s the time to break the chain up into two statements.

Now what

What’d I miss? What’s wrong?

Related Posts

White Paper

Software as a Medical Device (SaMD): What It Is & Why It Matters

Article

SaMD Cleared by the FDA: The Ultimate Running List

Article

Help Us Build an Authoritative List of SaMD Cleared by the FDA

Article

Testing Strategies for Bluetooth Medical Devices