Ruby convention for chaining calls over multiple lines
There is actually a section on that in the Ruby style guide:
Adopt a consistent multi-line method chaining style. There are two popular styles in the Ruby community, both of which are considered good - leading
.
(Option A) and trailing.
(Option B).
(Option A) When continuing a chained method invocation on another line keep the
.
on the second line.
# bad - need to consult first line to understand second lineone.two.three. four# good - it's immediately clear what's going on the second lineone.two.three .four
(Option B) When continuing a chained method invocation on another line, include the
.
on the first line to indicate that the expression continues.
# bad - need to read ahead to the second line to know that the chain continuesone.two.three .four# good - it's immediately clear that the expression continues beyond the first lineone.two.three. four
A discussion on the merits of both alternative styles can be found here.
In Ruby 1.9+ it's possible to write like this:
query = reservations_scope .for_company(current_company) .joins{property.development} .group{property.development.id} .group{property.development.name} .group{property.number} .group{created_at} .group{price} .group{reservation_path} .group{company_id} .group{user_id}
Much more readable, I think.
Here is a complete list of pros and cons of four options. Two of the options have not been mentioned in any other answer.
Pros and cons can be broken into unique ones and shared ones. Shared pros are the inverses of a unique con of another option. Similarly, shared cons are the inverses of a unique pro of another option. There are also some points that are pros for two options and cons for the other two.
To avoid repeating explanations, I describe each option’s shared pros and cons with just a summary of that point. Full details about a shared pro or con are available in the description of their inverse con or pro in another option’s unique section. For the points that are pros of two options and cons of the other two, I arbitrarily chose to put the full explanations in the set that starts with “.
at line beginning”.
For a shorter list that leaves the shared pros and cons implicit instead of repeating them, see this old version of this answer.
.
at line end
items.get.lazy. take(10). force
Pros
Shared with only one other option:- Continuing lines can be commented out freely, and comments can be added between lines
- Pastable into IRB/Pry
- Supported in Ruby 1.8
- When you read the initial line, it is clear that the expression continues
- Plenty of horizontal space for continuing lines
- Doesn’t require manual alignment of characters into columns
- Looks fine when viewed in a proportional font
- Has a minimum of punctuation, reducing typing and visual noise
Cons
Unique:- Continuing lines look strange on their own. You must read the preceding line to understand that they are a continuation.
- Indentation is not a reliable indicator that a line continues from the previous line – it could merely mean the start of a block.
- When editing the code, it is harder to comment out or reorder the last line
.
at line beginning
items.get.lazy .take(10) .force
Pros
Shared with only one other option:- When editing the code, it is easier to comment out or change the order of the last line – no need to delete and add
.
or\
.
- Continuing lines can be understood when seen on their own
- Plenty of horizontal space for continuing lines
- Doesn’t require manual alignment of characters into columns
- Looks fine when viewed in a proportional font
- Has a minimum of punctuation, reducing typing and visual noise
Cons
Unique:- When you read the initial line, it’s not immediately clear that the expression continues
- If you use this in your codebase, then when you read a line, you must always check the line after to make sure that it doesn’t affect the initial line’s meaning.
- The code silently breaks if you
#
comment out a continuing line, or add a comment between lines - You can’t paste this code into IRB/Pry without it being misinterpreted
- Not supported in Ruby 1.8 and below
.
at line beginning, indented to the previous .
items.get.lazy .take(10) .force
Pros
Shared with only one other option:- When editing the code, it is easier to comment out or change the order of the last line – no need to delete and add
.
or\
.
- When you read the initial line, it is clear that the expression continues
- Continuing lines can be understood when seen on their own
- Has a minimum of punctuation, reducing typing and visual noise
Cons
Unique:- Each line’s code must fit into less horizontal space
- Requires manual alignment of the
.
s into columns- It is easier if you have an editor plugin for aligning text, but still more work than using default indentation rules.
- Even if your editing setup includes a plugin for alignment, your coworkers’ setups may not.
- The code will look misaligned when viewed in a proportional font
- The code silently breaks if you
#
comment out a continuing line, or add a comment between lines - You can’t paste this code into IRB/Pry without it being misinterpreted
- Not supported in Ruby 1.8 and below
- When editing the code, it is harder to comment out or reorder the last line
\
at line end, .
at next line’s beginning
items.get.lazy \ .take(10) \ .force
Pros
Shared with only one other option:- Continuing lines can be commented out freely, and comments can be added between lines
- Pastable into IRB/Pry
- Supported in Ruby 1.8
- When you read the initial line, it is clear that the expression continues
- Continuing lines can be understood when seen on their own
- Plenty of horizontal space for continuing lines
- Doesn’t require manual alignment of characters into columns
- Looks fine when viewed in a proportional font
Cons
Unique:- Requires more typing
- Creates more visual noise
- When editing the code, it is harder to comment out or reorder the last line