I did some searching found some different methods and posts about creating a deep copy operator.
Is there a quick and easy (built-in) way to deep copy objects in Ruby? The fields are not arrays or hashes.
Working in Ruby 1.9.2.
I did some searching found some different methods and posts about creating a deep copy operator.
Is there a quick and easy (built-in) way to deep copy objects in Ruby? The fields are not arrays or hashes.
Working in Ruby 1.9.2.
Deep copy isn't built into vanilla Ruby, but you can hack it by marshalling and unmarshalling the object:
Marshal.load(Marshal.dump(@object))
This isn't perfect though, and won't work for all objects. A more robust method:
class Object
def deep_clone
return @deep_cloning_obj if @deep_cloning
@deep_cloning_obj = clone
@deep_cloning_obj.instance_variables.each do |var|
val = @deep_cloning_obj.instance_variable_get(var)
begin
@deep_cloning = true
val = val.deep_clone
rescue TypeError
next
ensure
@deep_cloning = false
end
@deep_cloning_obj.instance_variable_set(var, val)
end
deep_cloning_obj = @deep_cloning_obj
@deep_cloning_obj = nil
deep_cloning_obj
end
end
Source:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43424
I've created a native implementation to perform deep clones of ruby objects.
It's approximately 6 to 7 times faster than the Marshal approach.
https://github.com/balmma/ruby-deepclone
There is a native implementation to perform deep clones of ruby objects: ruby_deep_clone
Install it with gem:
gem install ruby_deep_clone
Example usage:
require "deep_clone"
object = SomeComplexClass.new()
cloned_object = DeepClone.clone(object)
It's approximately 6 to 7 times faster than the Marshal approach and event works with frozen objects.
Rails has a recursive method named deep_dup
that will return a deep copy of an object and, on the contrary of dup
and clone
, works even on composite objects (array/hash of arrays/hashes).
It's as easy as:
def deep_dup
map { |it| it.deep_dup }
end
I would suggest you use the ActiveSupport gem which adds a lot of sugar to your native Ruby core, not just a deep clone method.
You can look into the documentation for more information regarding the methods that have been added.
You can use duplicate gem for this.
It's a small pure ruby gem that able to recursively duplicate object It will duplicate it's object references too to the new duplication.
require 'duplicate'
duplicate('target object')
https://rubygems.org/gems/duplicate
https://github.com/adamluzsi/duplicate.rb
Automatic deep clone is not always what you want. Often you need to define a selected few attributes to deep clone. A flexible way to do this is to implement the initialize_copy
, initialize_dup
and initialize_clone
methods.
If you have a class:
class Foo
attr_accessor :a, :b
end
and you only want to only deep clone :b
, you override the initialize_*
method:
class Foo
attr_accessor :a, :b
def initialize_dup(source)
@b = @b.dup
super
end
end
Of course if you want @b
to also deep clone some of its own attributes, you do the same in b's class.
Rails does this (see https://github.com/rails/rails/blob/0951306ca5edbaec10edf3440d5ba11062a4f2e5/activemodel/lib/active_model/errors.rb#L78)
For more complete explanation, I learned it here from this post https://aaronlasseigne.com/2014/07/20/know-ruby-clone-and-dup/
Also check out deep_dive. This allows you to do controlled deep copies of your object graphs.
https://rubygems.org/gems/deep_dive