module Rack::App::Utils::DeepDup

Public Instance Methods

duplicate(object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 5
def duplicate(object)
  register = {}

  dup(register, object)
end

Protected Instance Methods

dup(register, object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 22
def dup(register, object)

  return registered(object, register) if registered(object, register)
  return register_duplication(register, object, object) unless identifiable?(object)

  case object

    when Array
      dup_array(register, object)

    when Hash
      dup_hash(register, object)

    when Range
      dup_range(register, object)

    when Struct
      dup_struct(register, object)

    when NilClass, Symbol, Numeric, TrueClass, FalseClass, Method
      register_duplication(register, object, object)

    else
      dup_object(register, object)

  end
end
dup_array(register, object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 56
def dup_array(register, object)
  duplication = dup_object(register, object)
  duplication.map! { |e| dup(register, e) }
end
dup_hash(register, object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 61
def dup_hash(register, object)
  duplication = dup_object(register, object)
  object.reduce(duplication) { |hash, (k, v)| hash.merge!(dup(register, k) => dup(register, v)) }
end
dup_instance_variables(register, object, duplication) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 86
def dup_instance_variables(register, object, duplication)
  return duplication unless respond_to_instance_variables?(object)

  object.instance_variables.each do |instance_variable|
    value = get_instance_variable(object, instance_variable)

    set_instance_variable(duplication, instance_variable, dup(register, value))
  end

  return duplication
end
dup_object(register, object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 82
def dup_object(register, object)
  dup_instance_variables(register, object, register_duplication(register, object, try_dup(object)))
end
dup_range(register, range) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 66
def dup_range(register, range)
  register_duplication(register, range, range.class.new(dup(register, range.first), dup(register, range.last)))
rescue
  register_duplication(register, range, range.dup)
end
dup_struct(register, struct) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 72
def dup_struct(register, struct)
  duplication = register_duplication(register, struct, struct.dup)

  struct.each_pair do |attr, value|
    duplication.__send__("#{attr}=", dup(register, value))
  end

  duplication
end
get_instance_variable(object, instance_variable_name) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 98
def get_instance_variable(object, instance_variable_name)
  object.instance_variable_get(instance_variable_name)
rescue NoMethodError
  object.instance_eval("#{instance_variable_name}")
end
identifiable?(object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 50
def identifiable?(object)
  object.class && object.respond_to?(:is_a?)
rescue NoMethodError
  false
end
register_duplication(register, object, duplicate) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 17
def register_duplication(register, object, duplicate)
  register[object.__id__]= duplicate
  duplicate
end
registered(object, register) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 13
def registered(object, register)
  register[object.__id__]
end
respond_to_instance_variables?(object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 116
def respond_to_instance_variables?(object)
  object.respond_to?(:instance_variables) && object.instance_variables.is_a?(Array)
rescue NoMethodError
  false
end
set_instance_variable(duplicate, instance_variable_name, value_to_set) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 104
def set_instance_variable(duplicate, instance_variable_name, value_to_set)
  duplicate.instance_variable_set(instance_variable_name, value_to_set)
rescue NoMethodError
  duplicate.instance_eval("#{instance_variable_name} = Marshal.load(#{Marshal.dump(value_to_set).to_s.inspect})")
end
try_dup(object) click to toggle source
# File lib/rack/app/utils/deep_dup.rb, line 110
def try_dup(object)
  object.dup
rescue NoMethodError, TypeError
  object
end