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)