Did you know that you can copy anobject in Ruby? Not only that, but there are two different methods to do this!
We will explore the differences in a moment, but first…
Why would you want to clone an object ?
Many objects in Ruby are mutable, you can change them.
If you want to change an object but keep a copy of the original then you can clone it.
You may want an array with all the elements but the first one.
a = [1,2,3,4,5] a[1..-1] # [2,3,4,5]
b = a.clone b.shift #  b # [2,3,4,5]
Both examples allow you to keep the original array.
Dup & clone are not analias of each other like it happens with other Ruby methods (map/collect), there a few small differences between them.
Exploring the sameness & difference between two things is a great way to improve your understanding .
Both methods copy an object, the difference is that
dup doesn’t copy the object attributes.
What object attributes?
a = Object.new.freeze b = a.dup b.frozen? # false b = a.clone b.frozen? # true
Ruby 2.4 includes an option for
clone to ignore the frozen status of the cloned object.
a.clone(freeze: true) a.clone(freeze: false)
There is more to copying an object than meets the eye.
When you make a copy, with either
clone , you are making a shallow copy .
This means that objects contained within other objects won’t be copied.
If you have an array ofstrings, only the array will be copied, not the strings themselves.
See for yourself:
original = %w(apple orange banana) copy = original.clone original.map(&:object_id) # [23506500, 23506488, 23506476] copy.map(&:object_id) # [23506500, 23506488, 23506476]
The object ids are the same even after cloning the array, so we have the same strings.
You could solve that with this:
This results on both the array & the strings being cloned, but notice that this only goes one level deep. You can try the deep_dup method from ActiveSupport as an alternative.
You have learned about cloning objects in Ruby! Including the differences between the dup & clone methods, and shallow copy vs deep copy.
Thanks for reading!