I have a method that iterates over some records and does something with them, optionally yielding a result -- something analogous to:
@evens = []
def foo(numbers)
numbers.each do |r|
even = r % 2 == 0
@evens << r if even
yield "#{r}: #{even}" if block_given?
end
end
I have a second method that fetches records and passes them to the first method, something analogous to:
def bar(count)
numbers = (0..count).to_a
foo(numbers)
end
I want to change this method to also take an optional block, yielding the results from the first method. What I've come up with so far:
def bar(count)
numbers = (0..count).to_a
foo(numbers) do |result|
yield result if block_given?
end
end
This feels like about two more lines and one more if block_given?
check than I ought to need. Is there a more concise way to simply say "yield whatever this method call yields, if anything"?
When defining a method in Ruby, you can also optionally define the block as a special named argument:
def bar(count, &block)
#...
end
Then, in the method, you can pass the block (or generally: any Proc object) as a block to a method. Thus, the following method will be fully equivalent to your bar
method:
def bar(count, &block)
numbers = (0..count).to_a
foo(numbers, &block)
end
Note that even when defining a &block
argument in the method's signature, it is not mandatory to pass a block. If you don't pass one, block
will be nil
in the method body.