The style guide is unclear on this case (other than just giving the opinion that it's weird and it is). I have a chain of hash/array functions to execute on a complex response object. I need to do a few sorts and selections and maps. Currently I just have a long chain of method calls but some of the blocks used for sorting and selecting are multiple lines and some are not.
Should I mix block definition types? Use only braces or only do..end blocks? Should I break it into multiple steps?
Also, if I refactor my blocks and turn them into methods, where would it be appropriate to put them? They don't really make sense in the context of the containing class as instance or class methods.
I looked around and could find no consensus on what is correct style but I am looking for a method that will pass the Ruby Style Guide (so most likely refactoring my blocks into methods, but where do I put them?)
Here is a bit of a contrived example:
def example1 (arr)
arr.sort do |a, b|
a_pieces = a.value.split ' '
b_pieces = b.value.split ' '
(a_pieces[1] + a_pieces[5]) <=> (b_pieces[1] + b_pieces[5])
end
.last[:some_value]
.select do |a|
a == 'something'
end
end
def example2 (arr)
arr.sort { |a, b|
a_pieces = a.value.split ' '
b_pieces = b.value.split ' '
(a_pieces[1] + a_pieces[5]) <=> (b_pieces[1] + b_pieces[5])
}
.last[:some_value]
.select { |a| a == 'something' }
end
I would use do ... end
blocks for multi-line and curly braces { ... }
for one-line code. I never use do ... end
for chaining methods, except when preceding for a multi-line block. I also chain methods in the same line as longer as the code is readable and the line is no longer than 80 chars.
So your example I will code it as below:
def example1 (arr)
arr.sort do |a, b|
a_pieces = a.value.split ' '
b_pieces = b.value.split ' '
(a_pieces[1] + a_pieces[5]) <=> (b_pieces[1] + b_pieces[5])
end.last[:some_value].select { |a| a == 'something' }
end
Although I probably will split it in two methods (actually three with the example1 one):
def sort_array(arr)
arr.sort do |a, b|
a_pieces = a.value.split ' '
b_pieces = b.value.split ' '
(a_pieces[1] + a_pieces[5]) <=> (b_pieces[1] + b_pieces[5])
end
end
def select_item(arr)
arr.last[:some_value].select { |a| a == 'something' }
end
def example1(arr)
select_item(sort_array(arr))
end
I'd do it something like this:
def example1(arr)
arr.sort_by { |a|
a_pieces = a.value.split
(a_pieces[1] + a_pieces[5])
}.last[:some_value]
.select { |a| a == 'something'}
end
sort
will be much slower than sort_by
if there is anything beyond a simple <=>
comparison of simple objects.
Stylistically, use {
...}
instead of do
...end
if you're returning a value, especially in a chain of methods. The "style guides" suggest using do
...end
when you're dealing with multiple lines in a block, but end.some_method
is fugly and confusing. Using {
...}
reminds us we are passing only values and cleans up the fugliness.
Remember, they're style guides, not laws, and are really common-coding practice guidelines to help us write code readable by everyone. Consistency is important, as is readability.
Also, a bare split
does the same things as split ' '
or split(' ')
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With