This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# Clonable provides a standard basis for adding deep cloneablity to a class
|
||||
# via the standard #dup and #clone methods.
|
||||
#
|
||||
# Cloneable was originally ported from Jim Weirich's Rake.
|
||||
# The current version is the work of Ken Bloom.
|
||||
#
|
||||
# DEPRECATED: A better approach is to provide a #deep_dup and and a #deep_clone,
|
||||
# then if a class needs these for #dup and #clone they can just alias them.
|
||||
#
|
||||
# CREDIT: Ken Bloom
|
||||
|
||||
module Cloneable
|
||||
|
||||
def initialize_copy(sibling)
|
||||
# First duplicate my superclass' state. Note that if it's duplicating
|
||||
# instance variables, this will be overwritten, but this is important
|
||||
# because we could be dealing with a C extension with state hidden from
|
||||
# the Ruby interpreter.
|
||||
super
|
||||
|
||||
# We want to know if we're being dup'ed or clone'd, because we want to
|
||||
# preserve the state of our internals the same way our state is being
|
||||
# preserved. (If we can't figure it out, we'll just use #dup.)
|
||||
operation = (
|
||||
copy_call = caller.find{|x| x !~ /'initialize_copy'/}
|
||||
copy_match = copy_call.match(/`(dup|clone)'/)
|
||||
copy_match ? copy_match[1] : :dup
|
||||
)
|
||||
|
||||
sibling.instance_variables.each do |ivar|
|
||||
value = sibling.instance_variable_get(ivar)
|
||||
|
||||
# Set my instance variable to be a #dup or #clone
|
||||
# or my sibling, depending on what's happening to me right now.
|
||||
instance_variable_set(ivar, value.send(operation))
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Is there a more robust means of determining if clone or dup is used?
|
||||
#def clone
|
||||
# @_copy_operation = :clone
|
||||
# super
|
||||
#end
|
||||
#
|
||||
#def dup
|
||||
# @_copy_operation = :dup
|
||||
# super
|
||||
#end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
# OLD VERSION
|
||||
|
||||
#module Cloneable
|
||||
# def clone
|
||||
# sibling = self.class.new
|
||||
# instance_variables.each do |ivar|
|
||||
# value = self.instance_variable_get(ivar)
|
||||
# sibling.instance_variable_set(ivar, value.dup) #rake_dup)
|
||||
# end
|
||||
# sibling
|
||||
# end
|
||||
# alias_method :dup, :clone
|
||||
#end
|
||||
|
||||
Reference in New Issue
Block a user