02.09.06
Ruby: (Deep) Copy Object
I wanted to make an object. Then copy it. Then change that copy and leave original object intact. But I did not know how to do it. When I do not know how to do something, I always ask wtr-general mailing list. I posted my question. Then I though it would be nice if I explained why I want to copy an object. But it got pretty long, so I put it at my blog.
I got a reply. “Try Object#clone”. Could it be that easy?! It could be. After all, this is Ruby. But no, it is not that easy. It did not work. Original object was changing with it’s duplicate.
Output:
#<Page:0x2820ae0 @url="app.com/view.aspx", @texts=["File > View", "File added."]>
#<Page:0×2820a98 @url=”app.com/view.aspx”, @texts=["File > View", "File added."]>
But now I new where to look. So I typed “ri Object#clone” and “ri Object#dup” at Command Prompt (and even looked at http://www.ruby-doc.org/core/). It said (at both places, for both Object#clone and Object#dup):
“Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference.”
So, it creates a “shallow” copy. I do not need this. I need a “real” copy.
Google helped me. I searched for “ruby copy object” and found http://www.rubygarden.org/ruby?Make_A_Deep_Copy_Of_An_Object. Secret word is “deep” copy.
I added this to class Page (and replaced page_view.clone with page_view.deep_clone) and got what I needed!
Output:
#<Page:0x4c1dd10 @url="app.com/view.aspx", @texts=["File > View"]>
#<Page:0×4c1dc50 @url=”app.com/view.aspx”, @texts=["File > View", "File added."]>
I do not understand how it works, and I do not care, as long as it works.


Nolan Eakins said,
March 21, 2007 at 9:27 pm
The way your solution works is pretty easy. It serializes the data out to text and then loads it up into a new set of objects. That may cause some overhead though. The only other way to do a deep copy is to recursively clone/dup each instance variable.
aoaoniu1985 said,
March 2, 2008 at 8:21 am
Thanks a lot about this useful tip. I am working on the Ruby programming assignment in the Programming Language class and the prof want us to code a deep dup method for a class. It seems I find a solution from you. Thank you.
Željko Filipin’s Blog on Software Testing » Who are you? said,
March 19, 2008 at 10:12 pm
[...] You are probably from US, Croatia, India, or UK. Top 5 content is front page, Watir category, Ruby: (Deep) Copy Object post (a surprise for me), e-mail category and about me [...]
daltxguy said,
May 20, 2008 at 1:13 pm
Wow! This is just what I was looking for and it made my fix very easy. I had a case where it seemed more natural to pass an entire object to a method but it necessarily needed to do some destructive changes to it while doing its thing.
I suppose if I had realized earlier that Ruby passes everything by reference and that if I passed an object to a method, then even though the local identifier to it is a copy, the thing it points to is still the same object then I might have designed it differently.
Unless I have a completely wrong paradigm, I would think making copies of objects is a rather common thing to want to do, I’m glad you found a nice easy way to do it. I would have thought that wth Ruby, every class would automatically have some kind of “deep_clone” method builtin.
Perhaps the popularity of this page is an indication that this is big missing?
Željko Filipin said,
May 20, 2008 at 1:55 pm
As far as I remember, deep copy is intentionally not implemented because it’s use is discouraged.