Search code examples
rubystringupcase

Weird behavior of #upcase! in Ruby


Consider the following code:

@person = { :email => '[email protected]' }
temp = @person.clone
temp[:email].upcase!

p temp[:email]     # => [email protected]
p @person[:email]  # => [email protected], why?!

# But
temp[:email] = '[email protected]'
p @person[:email]  # => [email protected]

Ruby version is: "ruby 2.1.0p0 (2013-12-25 revision 44422) [i686-linux]".

I have no idea why is it happening. Can anyone help, please?


Solution

  • In the clone documentation you can read:

    Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. clone copies the frozen and tainted state of obj.

    Also pay attention to this:

    This method may have class-specific behavior. If so, that behavior will be documented under the #initialize_copy method of the class.

    Meaning that in some classes this behaviour can be overrided.

    So any object references will be kept, instead of creating new ones. So what you want is a deep copy you can use Marshal:

    temp = Marshal.load(Marshal.dump(@person))