AR clone interaction with initialization logic in model


Assume an AR model with an after_initialize method, which is used to
initialize attribute values. An example would be:

class X < ActiveRecord::Base

def after_initialize
self.attr1 = 0

Further assume that x is an instance of X, and x.attr1 has been assigned
the value 3.

If I do y = x.clone, and interrogate the value of y.attr1, I’ll get 0.
This makes sense given the source code for AR#clone. But I expected the
value of attr1 to be 3, not 0.

I would think that clone should completely instantiate the new object,
and then assign the attribute values from the original object.

Is the current behavior a bug, or am I missing some important
philosophical point.


One way around this is to modify the after_initialize logic to not
assume that the attribute values should always be set, like so:

class X < ActiveRecord::Base

def after_initialize
if self.new_record?
self.attr1 ||= 0

In a clone situation, attr1 will already have a value and therefore,
won’t be initialized to a default value.

Still, I feel like clone has a bug in it. Here’s what happens in a
regular Ruby object:

class X
attr_accessor :val

def initialize
@val = 5

x =
=> 5
x.val = 23
=> 23
y = x.clone
=> #<X:0x2c33148 @val=23>

The value of @val in the cloned object is 23, not 5.

While I concede that after_initialize is a standalone method that
officially has nothing to do with Ruby object initialization, I still
feel like the clone method should set the attribute values after the
object is instantiated.