Home > Net >  Different behavior between multi-line vs. in-line block
Different behavior between multi-line vs. in-line block

Time:01-12

I am curious why these are producing different outputs. The desired output is an array of ActiveRecord records.

When using an in-line block, it appears to be doing the ActiveRecord lookup, but subsequently nests the original array (minus the rejected elements) inside of another array and appends the nested arrays to the variable.

When using a multi-line block, the expected behavior occurs, i.e. the ActiveRecord lookup occurs and the identified records are appended to the variable.

x = []
y = ["", "1353", "1155"]
x << y.reject!(&:empty?).each { |i| User.find(i) }
# => ["1353", "1155"]
x
#=> [["1353", "1155"]]

vs

x = []
y = ["", "1353", "1155"]
y.reject!(&:empty?)
y.each do |i|
  x << User.find(i)  
end  
# => ["1353", "1155"]
x
#=> [#<User:0x00007fc7fbacc928
#  id: 1353,
#  login: nil,
...

CodePudding user response:

The difference is that .each returns the array itself, so

[1,2,3].each { nil }
# [1,2,3]

so you are appending the rejected Y numbers in X, and your .each is being useless on the first example (that's also why it is an array of array, because '<<' inserts the element array inside your array, and not all the individual elements)


In your second example, your 'each' is in fact appending the elements to your array inside the block, so no "return" dependency. If you want to do it on single line, you would have to do

y.reject(&:empty?).each { |i| x << User.find(i) }

so it would do the calculation inside de block and if you want each loop to return the value inside the block you should use 'map' instead of 'each', and the 'concat' or ' ' to sum the arrays (so it sums or concats each individual elements), so

x.concat(y.reject(&:empty?).map{ |i| User.find(i) })

OBS: As @tadman suggested on comment, I also removed the "bangs" for reject, as the 'reject!' method does not expect to always return all the values, check his comment for more information

  • Related