setter method return self not work, it's a bug?

ruby

Solution

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 }

Problem

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?

Original source

Related problems