ActiveRecord::Base#cloneは本当はcloneではなかったらしい
freezeはコピーされない
Object#clone
>> class A >> end => nil >> a = A.new => #<A:0x2480948> >> a.taint => #<A:0x2480948> >> a.freeze => #<A:0x2480948> >> a.tainted? => true >> a.frozen? => true >> b = a.clone => #<A:0x244d55c> >> b.tainted? => true >> b.frozen? => true
ActiveRecord::Base#clone
?> obj1 = Article.new => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> obj1.taint => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> obj1.freeze => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> obj1.tainted? => true >> obj1.frozen? => true >> obj2 = obj1.clone => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> obj2.tainted? => false >> obj2.frozen? => false
特異メソッドもコピーされない
Object#clone
>> a = A.new => #<A:0x2480948> >> class << a >> def hello >> "hello" >> end >> end => nil >> b = a.clone => #<A:0x247b81c> >> a.hello => "hello" >> b.hello => "hello"
ActiveRecord::Base#clone
?> obj1 = Article.new => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> class << obj1 >> def hello >> "hello" >> end >> end => nil >> obj2 = obj1.clone => #<Article id: nil, title: nil, body: nil, created_at: nil, updated_at: nil> >> obj1.hello => "hello" >> obj2.hello NoMethodError: undefined method `hello' for #<Article:0x23c4ef0> from /Users/sogo/code/rails/edge_rails/vendor/rails/activerecord/lib/../../activemodel/lib/active_model/attribute_methods.rb:240:in `method_missing' from /Users/sogo/code/rails/edge_rails/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:38:in `method_missing' from (irb):26
インスタンス変数をコピーしているだけですね
activerecord/lib/active_record/base.rb
# Returns a clone of the record that hasn't been assigned an id yet and # is treated as a new record. Note that this is a "shallow" clone: # it copies the object's attributes only, not its associations. # The extent of a "deep" clone is application-specific and is therefore # left to the application to implement according to its need. def clone attrs = clone_attributes(:read_attribute_before_type_cast) attrs.delete(self.class.primary_key) record = self.class.new record.send :instance_variable_set, '@attributes', attrs record end