Reputation: 24118
What are the conventions for this?
I use the folowing style, but not sure it is the preferred one since if I miss a dot at the end I can run into a lot of issue without realising that.
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}.
group{fee_paid_date}.
group{contract_exchanged_date}.
group{deposit_paid_date}.
group{cancelled_date}.
select_with_reserving_agent_name_for(current_company, [
"developments.id as dev_id",
"developments.name as dev_name",
"properties.number as prop_number",
"reservations.created_at",
"reservations.price",
"reservations.fee_paid_date",
"reservations.contract_exchanged_date",
"reservations.deposit_paid_date",
"reservations.cancelled_date"
]).reorder("developments.name")
query.to_a # ....
So what are the conventions for chaining methods over multiple lines and which one should I prefer?
NOTE: I couldn't find a good example from the Ruby coding style guide.
Upvotes: 47
Views: 27377
Reputation: 30428
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 enditems.get.lazy.
take(10).
force
.
at line beginningitems.get.lazy
.take(10)
.force
.
or \
.#
comment out a continuing line, or add a comment between lines.
at line beginning, indented to the previous .
items.get.lazy
.take(10)
.force
.
or \
..
s into columns
#
comment out a continuing line, or add a comment between lines\
at line end, .
at next line’s beginningitems.get.lazy \
.take(10) \
.force
Upvotes: 30
Reputation: 56665
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 line one.two.three. four # good - it's immediately clear what's going on the second line one.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 continues one.two.three .four # good - it's immediately clear that the expression continues beyond the first line one.two.three. four
A discussion on the merits of both alternative styles can be found here.
Upvotes: 61
Reputation: 1790
The reason why I choose the dot in the end of the line is that it will allow you to paste code in an IRB session. Also, you can't comment lines in the middle of the multi-line code if you use the dots in the beginning of the lines. Here's a good discussion to read: https://github.com/bbatsov/ruby-style-guide/pull/176
Upvotes: 12
Reputation: 15299
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.
Upvotes: 35