I want to iterate an array of strings, and assign each of them to a fresh instance of class User, and I expect that I will got an array of User objects:
class User
def name=(name)
@name = name
self
end
end
original_array = ["aaa", "bbb", "bbb"]
result = original_array.collect { |str| User.new.name = str }
but the result is an array of strings!
puts result.inspect # => ["aaa", "bbb", "bbb"]
puts result === original_array # => true
I have no idea of where I went wrong?
What's wrong here is that User.new.name = str
returns str
, so the value of str
gets collected.
Why does it return str
? Because, opposed to any other Ruby method, every Ruby setter method returns the passed value, regardless the returned value in the method. For more infos about this behaviour you can check this other SO answer.
Below a IRB-ready Proof of Concept:
def name=(name)
@name = 'another value'
end
returned_value = (self.name = 'a value')
returned_value #=> 'a value'
@name #=> 'another value'
What you want can be done in this ways:
This syntax is valid for any Ruby object, as it uses Object#tap
:
User.new.tap { |v| v.name = str }
If User
is an ActiveRecord
model, as I guess, you can use one of these slightly shorter syntaxes:
User.new name: str
User.new { |v| v.name = str }
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