07/09/2018, 15:46

Ruby Object Clone and Duplication

Lately I've faced some Ruby Object Problems Actually this is the OOP object copy problem.But I dont know much about OOP so... Ok, enough trash talking. Let's do some code I used rails c for this mini testing test = {:a => 1, :b => 2 } a = test b = test a[:a] = 3 puts a {:a => ...

Lately I've faced some Ruby Object Problems
Actually this is the OOP object copy problem.But I dont know much about OOP so...
Ok, enough trash talking. Let's do some code

I used rails c for this mini testing

test = {:a => 1, :b => 2 }
a = test
b = test
a[:a] = 3

puts a

{:a => 3,:b => 2 }

puts b

{:a => 3,:b => 2 }

puts test

{:a => 3,:b => 2 }

Even I haven't touched b and test yet. Still these values are changed when I changed a

Solution :

Using dup and clone

a = test.dup
a[:a] = 3

=> a = {:a => 3,:b => 2 }
b = test = {:a => 3,:b => 2 }

a = test.clone
a[:a] = 3

=> a = {:a => 3,:b => 2 }
b = test = {:a => 3,:b => 2 }

I couldnt find the different between these 2 methods
So I decided to go a little bit deeper

TEST1

dup :

a = Object.new
def a.foo; :foo end
p a.foo
# => :foo
b = a.dup
p b.foo
# => undefined method `foo' for #<Object:0x007f8bc395ff00> (NoMethodError)

clone:

a = Object.new
def a.foo; :foo end
p a.foo
# => :foo
b = a.clone
p b.foo
# => :foo

Frozen state :

a = Object.new
a.freeze
p a.frozen?
# => true
b = a.dup
p b.frozen?
# => false
c = a.clone
p c.frozen?
# => true

conclusion 1:

They both create a shallow copy of an object (meaning that they don't copy the objects that might be referenced within the copied object). However, #clone does two things that #dup doesn't:

copy the singleton class of the copied object
maintain the frozen status of the copied object

*https://coderwall.com/p/1zflyg/ruby-the-differences-between-dup-clone

class Klass
  attr_accessor :str
end

module Foo
  def foo; 'foo'; end
end

s1 = Klass.new #=> #<Klass:0x401b3a38>
s1.extend(Foo) #=> #<Klass:0x401b3a38>
s1.foo #=> "foo"

s2 = s1.clone #=> #<Klass:0x401b3a38>
s2.foo #=> "foo"

s3 = s1.dup #=> #<Klass:0x401b3a38>
s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>

conclusion 2:

In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance.

When using dup, any modules that the object has been extended with will not be copied.

*http://ruby-doc.org/core-2.2.3/Object.html#method-i-clone

Assume we had ActiveRecord working

camp = Campaign.find(1)
clone = camp.clone
dup = camp.dup

camp : {:id => 1, :name => "test campaign 1"}
clone : {:id => 1, :name => "test campaign 1"}
dup : {:id => nil, :name => "test campaign 1"}

conclusion 3:

clone will have all of camp's attributes including id while dup
=> clone.save will excute the update method (update the camp object)
and dup.save will excute the new method (create new object exactly the save attributes with camp object)

0