Search code examples
rubyclone

Using gsub on cloned hash in Ruby modifies original


I'm facing a problem in which I can't substitute a string in a cloned hash without affecting its original. I'd better explain using an example:

product_attributes = raw_attributes.clone

# do some stuff on product_attributes like removing hash elements using "select!"

puts product_attributes[:code]
# => 64020-001
puts raw_attributes[:code]
# => 64020-001

product_attributes[:code].gsub!(/[\/|\-][0-9\.]*$/, "")

puts product_attributes[:code]
# => 64020
puts raw_attributes[:code]
# => 64020

I use Ruby 1.9.3p327 on OSX.

Is this a known issue (or even a feature)? Or am I doing something wrong?


Solution

  • clone only makes a shallow copy of the array, so the elements are copied over rather than cloned themselves. See What's the most efficient way to deep copy an object in Ruby? for some good discussion about how to do a deep copy efficiently.

    If you just need to deep clone this one value:

    product_attributes = raw_attributes.clone
    product_attributes[:code] = product_attributes[:code].clone