company-logo

Elements of Ruby Style

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?

  1. Dan Manges Reply

    I still use do/end instead of the braces when tacking a method call on to the end of a multiline block.

    list.map do |x|
    x + 3
    end.sort

  2. Harry Reply

    Should “return if x = null” be “return if x == nil” ? And if so, I also tend to adopt the JavaScript style of putting the constant first. So …

    return if nil == x

    That way if you forget the second equal sign, the interpreter throws an error.

  3. Chris O'Sullivan Reply

    This is great Noel!

    I’d also quickly add:

    Use ‘and’ not ‘&&’
    Use ‘or’ not ‘||’

  4. Norman Clarke Reply

    This was a good read – a clear, terse summary of the formatting you see in most good Ruby code. I just have one small quibble:

    x = if boolean then 3 else 5 end

    might just be better expressed using the ternary operator:

    x = boolean ? 3 : 5

  5. Ryan Tomayko Reply

    Whitespace errors waste people’s time. They make diffs overly noisy and can cause needless merge conflicts. There should be no whitespace at the end of a line or file. Your editor should display whitespace errors and your source control system should not allow files with whitespace errors to be committed without some explicit confirmation step.

  6. khelll Reply

    Great article, could be expressed as ruby code conventions.

  7. chris Reply

    Seems like your indentation isn’t showing up – kinda ironic for an article about style….

  8. Brandon Reply

    2 spaces? 80 columns? Are you kidding me? What are you in 80×25 text mode on a 386? That’s barely any indentation at all on a large display. Barely even noticeable. I’d have to concentrate to notice that indentation.

  9. Nick Quaranto Reply

    Definitely a good guide. Perhaps a ‘school’ of proper ruby style should be started, that lists example programs, code snippets…and of course can make fun of horrible code. ;)

  10. Russ Reply

    @3: ‘and’ and ‘or’ have some subtle precedence issues. They are useful in places but it is recommended to use &&, ||.

  11. lowell Reply

    i didnt get into 2-space soft tabs in textmate until i converted to haml in rails from erb. now i’m hooked, and use 2 spaces for tabs even in erb-laden rails projects.

    i dunno about that 80 column limit though. i find that breaking up longer lines makes for some un-sexy code, since it’s usually just a handful of text being moved.

  12. Tim Case Reply

    I don’t agree with the if statement being long and overredundant and not in the spirit of ruby. That style of if statement is extremely quick and easy to read, especially if the code inside the if statement is complex. The chained method on the multiline blocks are starting to slide into getting cute and clever vs. clear and easily readible IMO. I think my standards would clash with yours and maybe these standards come down to personal taste?

    http://blog.objectmentor.com/articles/2008/06/26/now-and-for-something-completely-different

  13. Pingback: Weekend Ruby: Coding Quality with Style | noizZze

  14. Carla Nielsen Reply

    Anyone who doesn’t use 3 spaces for indentation is in error.

  15. Alin Reply

    Ruby way:
    return if x.nil?
    instead of
    return if x == nil

  16. Mike Reply

    Python, not just Java, prefers 4 space indentation according to PEP 8.

  17. jerome Reply

    “I probably would avoid doing something like user.manager.company.name.size as a single line”

    hu ? how many lines then ???

  18. Sean O'Halpin Reply

    Hi Noel,

    I enjoyed your post. Some observations:

    = Parentheses

    The general rule for parentheses is to use them in functional expressions, leave them out in statements, e.g.

    x = o.func(args)

    o.meth args

    = Use if statements as statements

    Did you mean ‘Use if statements as expressions’?

    Neither of your alternatives for if statements are ‘idiomatic’ – ‘then’ is almost a deprecated keyword. Perhaps this:

    x = if boolean
    3
    else
    5
    end

    but then you might as well use the ternary ?: operator:

    x = boolean ? 3 : 5

    By the way, using if as an expression confuses a lot of Ruby newbies. Why add to the cognitive load? At best, it’s a tricksy little flourish.

    = Use of Ruby idioms

    Symbol#to_proc is currently a Rails idiom, not a Ruby one. Also, the Rails implementation is incredibly slow. That’s why some people don’t like it.

    = Only use trailing if statements in guard clauses

    Surely you mean:

    return if x == nil

    = Multiple return statements

    Seeing any ‘return’ in Ruby code makes me sigh. Maybe OK for a quick exit after parameter checks.

    = Block layout

    The braces vs do … end convention is that braces are used in functional expressions, do … end in statements, e.g.

    result = list.map{|x| … }

    list.each do … end

    Nothing to do with how many lines they go over. It just so happens that most Rubyists don’t like semi-colons, so they make a do … end block go over multiple lines to avoid them.

    = Stringing things together

    To clarify your point: chaining is fine on enumerable methods that return enumerables – you’ll always have an enumerable to act on. Chaining is not such a good idea where any intermediate method may return nil (your second example) which is also a violation of the http://en.wikipedia.org/wiki/Law_of_Demeter (though this can be overstated).

    Regards,
    Sean

  19. Ingemar Reply

    @Chris O’Sulliva: ‘and’ and ‘&&’ is not really the same… There are several good blog posts about this allready.

  20. Pingback: Dev Blog AF83 » Blog Archive » Veille technologique : 37 Signals, OOo 3.0, MAMA, Tag Maps, CSS3, benchmarks, Merb

  21. Pingback: links for 2008-10-20 | Libin Pan

  22. Glenn Reply

    This is a great article.

    A couple of points:

    if boolean
    x = 3
    else
    x = 5
    end

    is much clearer than:

    x = if boolean then 3 else 5 end

    So what is you save 4 lines?

    I agree with the comnment that the second one is overly cutesy.

    Someone said ‘and’ is better, and someone else said that ‘&&’ is better. Which is correct?

  23. JT Reply

    Interesting topic for an article and useful writeups are always appreciated and shine on the author. Thank you! Value of your article is tremendously diminished by the fact none of the examples actually work (formatting not applied). Lack of proofing (to notice the errant examples) is a real disappointment; conveys you don’t care about your work and/or the readers.

  24. Phil Reply

    I’ve never seen ruby code that uses “then” that wasn’t over three years old. It’s unnecessary and should be omitted.

    Symbol#to_proc is not part of Ruby 1.8, so it should only be used in Rails apps, and even there you take a perf hit so it shouldn’t be done in tight loops.

    For do/end vs {} blocks, another common rule of thumb is to use do/end when you’re performing an operation for its side-effects and {} when it’s meant to be used for its return value. This usually is in sync with the single/multi-line rule, but not always.

  25. Bob Aman Reply

    return if x = nil

    This code is buggy.

  26. Bob Aman Reply

    Chris O’Sullivan is wrong to suggest using “and” over “&&” and “or” over “||”. The “and” and “or” operators have extremely low precedence and should only be used for flow control. That IS what they were designed for after all. Using them instead of their counterparts leads to bugs, most often with assignment.

    It may be tempting to make your code read more like English, but that should not be your goal. Remember, “the goals of well-styled code are correctness and simplicity, in that order.”

  27. Bob Aman Reply

    “There should be no whitespace at the end of a line or file.”

    +1

    Re: Phil and Symbol#to_proc

    I disagree. It has its place outside Rails apps. Since Ruby 1.9 supports it, it’s a no-brainer for legitimate usage in Ruby 1.8 as well. However, as usual, one should not require ActiveSupport to obtain the functionality.

  28. Don Reply

    @Sean: “By the way, using if as an expression confuses a lot of Ruby newbies. Why add to the cognitive load? At best, it’s a tricksy little flourish.”

    I agree that not everyone would want to use it, but it can have a clear semantic meaning and maybe even contribute to readability. To me, the following means “by the time this chunk of code is over, we’ll know what ‘body_mass_index’ is:”

    body_mass_index = if person.gender == male
    # some math
    else
    # some different math
    end

    I use this structure if the code in the if-statement has no real side effects and I just care about the result. Then I can see at a glance what this section does.

  29. blaxter Reply

    2 spaces is the same as no indentation. The discussion could be between 8 or 4 spaces. I definitely prefer 4 spaces.

    2 spaces is insane!

  30. Pingback: Pathfinder Development » Ruby Stylista

  31. bubba Reply

    I vote for 21.7 spaces.

  32. Pingback: เร็วส์ หกสิบหก » นั่งเทียนเขียนข่าว#20

  33. leethal Reply

    I prefer to not have a space after the curly bracket for block arguments. {|foo| foo.bar }, not { |foo| foo.bar }

  34. Apie Reply

    Sentences that start with “You should…” normally loose me at the ‘should’ :)

  35. Joe Zack Reply

    Call me crazy, but I think this

    a_very_long_method_name(
    argument1,
    a + b,
    arg 3
    )

    looks much better than this

    a_very_long_method_name(argument1,
    a + b, arg 3)

    or this

    a_very_long_method_name(argument1,
    a + b, arg 3)

  36. apeiros Reply

    I have to say that in the following code:

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

    ‘is_active’ is violating my feelings :)
    Using prefixes like ‘is_’, ‘get_’ and ‘set_’ is so java (and yes, java is a synonym for ugly here). In ruby instead of prefixing with ‘is_’ you’d use the postfixed questionmark, e.g.:

    all_users.select(&:active?).map(&:name).sort

    Regards
    apeiros

  37. ab5tract Reply

    2 spaces is the only way to go. For one, not everyone uses TextMate (big shock to many, I know). Even for those who do, many times it is just as easy to use a CLI editor for a quick fix. Dealing with 4/8 spaces in that context is “insane”. I can’t imagine what kind of res/font size you would be using to not notice a 2 space indent… That said, this is really a project-by-project issue, where the team decides what standard to adopt. That said, when it comes up, in a “tab vs whitespace” debate, whitespace wins. And it’s usually the 2 space variety. This is often a LCD issue, and older coders will chafe at tabs and blanch at >2 space indents. Since you like your older coders, you go with them.

    In terms of ternary operator, the author provides no legitimate reason not to use it. The justification is “I don’t like it”. This is ridiculous. The ‘? : ‘ operator is quite definitely a “Ruby idiom”, and is significantly more readable then the overly-verbose single-line example given.

  38. Pingback: ESPN Dev Blog » Blog Archive » Ruby Style Guides and Tools

  39. dani Reply

    “Indenting Ruby code four spaces indicates that you are a very recent convert from Java”

    nice argument!

  40. Pingback: vBharat.com » Pathfinder Development » Elements of Ruby Style

  41. Nona Reply

    Please divorce your current editor if it hides code on long lines. Any programmer’s editor will do the correct thing and wrap.

  42. Pingback: Ruby Style Guides and Tools: How to Write Good Looking Ruby : WebNetiques

  43. gw Reply

    2 spaces? no way. 80 char limit? no way. Standard if structure is much clearer than the proposed alternatives. Avoid ternary? Pfft, don’t think so–especially for short lines. Leave out last return? Don’t care for that at ll. Code should be explicit wherever possible. return x is instantly recognizable as to purpose and function. Stringing things together goes “overboard” very quickly IMO. smaller steps on more lines is usually easier to read than one-liner magic.

    I like Ruby, but I don’t care for a lot of the style and idioms that are completely counter to most other languages and practices just so the people using them can be the “kewl kids.” Worse is the flogging certain community folks give when their arbitrary favorite style isn’t followed. It feels a lot like royal manners–designed to make a small group feel elite because they follow some arbitrary rules. It’s just style snobbery and doesn’t fit within the usually friendly atmosphere of teh Ruby community (slowly being eroded as elitism spreads).

  44. Sho Reply

    @gw:

    Most Ruby users that I know care deeply about the “look and feel” of the language they use – that’s the whole reason they love Ruby so much. Efforts to come up with the “best practise” for writing clear, understandable, good looking code are not elitism or an effort to become “cool kids”. It’s more an effort to arrive at some kind of ideal standard form, by people who care deeply about style and function.

    And more than 2 spaces is ridiculous. Maybe 4 spaces is necessary for Java, a much more verbose language, else the indentation gets lost in a sea of code .. but Ruby is far more concise. 2 spaces is fine in well written code.

    Also, I disagree that Ruby is becoming less friendly. There’s a few new corporate wannabe wankers around, sure, but you get that anywhere. The ruby people I know are friendly as anything. Calm down, cheer up and have a little more faith in people.

  45. Pingback: เร็วส์ หกสิบหก » นั่งเทียนเขียนข่าว#22

  46. Pingback: Juixe TechKnow » The Rubyist: October Edition

  47. Barry Reply

    @Harry,

    Maybe even
    return if x.nil?

  48. Kenn Reply

    Of course the beauty of using tabs for indentation is that your editor will display them at whatever width you prefer, while not imposing your own width preferences on others.

    For the record, I do single-tab indent and display them with a width of four characters. Everyone wins.

  49. Pingback: CSS Coding Standards | Samurai Coder

Leave a Reply

*

captcha *