Enumerable#many? now forwards all block parameters


Enumerable methods can be chained together to form complex queries. For example, to find the first element in an array that is greater than 5 and less than 10, we can use the following code:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].select { |n| n > 5 }.find { |n| n < 10 }

It is expected that each enumerable method passes the block parameters to the next method in the chain. However, this is not the case with Enumerable#many?.

Before

Let’s look at an example at how a similar method, Enumerable#any?, works. Enumerable#any? returns true if an array has at least 1 element. It also accepts any block or parameter passed to it.

irb(main):01:0> [1, 2, 3].any?(Integer)
=> true
irb(main):02:0> %w[ant bear cat].any? { |word| word.length >= 3 }
=> true
irb(main):03:0> [].any?
=> false

When chained with each_with_index and passed to a block, it also passes the index parameter as well.

irb(main):01:0> [1, 2, 3].each_with_index.any? do |element, index|
puts index
end
0
1
2
=> false

Let’s try something similar with Enumerable#many?.

irb(main):01:0> [1, 2, 3].many?(Integer)
/Users/swaathi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.3.1/lib/active_support/core_ext/enumerable.rb:144:in 'many?': wrong number of arguments (given 1, expected 0) (ArgumentError)
irb(main):02:0> %w[ant bear cat].many? { |word| word.length >= 3 }
=> true
irb(main):03:0> [].many?
=> false

Clearly, it accepts blocks but no parameters. However when chained with each_with_index and passed to a block, it does not pass all the parameters.

irb(main):01:0> [1, 2, 3].each_with_index.many? do |element, index|
puts index
end
nil
nil
nil
=> false

After

After this PR Enumerable#many? passes all the parameters to the block.

irb(main):01:0> [1, 2, 3].each_with_index.many? do |element, index|
puts index
end
0
1
2
=> false

Join Our Newsletter