Из-за многочисленных ограничений, связанных с первоначальной идеей упаковки всех вызовов в один класс, я немного переработал его, но он работает точно так же.
def proxy__enwrap(obj)
isClass = obj.is_a?(Class)
oldClass = isClass ? obj : obj.class
sNewClass = "Proxy#{oldClass.to_s}"
code = <<-EOF
class #{sNewClass}
include InstanceProxy
def self.__cinit__(obj)
@@__cobj__ = obj
end
def self.__cget__
@@__cobj__
end
def self.method_missing(m,*args,&block)
if @@__cobj__.respond_to? m
retVal = @@__cobj__.public_send(m,*args,*block)
return proxy__enwrap(retVal)
else
puts "ERROR " + m.to_s + "(" + args.to_s + ") + block?"
#Throw error
end
end
end
#{sNewClass}.__cinit__(#{oldClass.to_s})
if isClass
return #{sNewClass}
else
return #{sNewClass}.new(obj)
end
EOF
::Kernel.eval(code)
end
module InstanceProxy
def method_missing(m,*args,&block)
retVal = @__obj__.__send__(m,*args,&block)
return proxy__enwrap(retVal)
end
def initialize(obj)
@__obj__ = obj
end
end
XXApplication = Application
::Object.const_set "Application", proxy__enwrap(Application)
В настоящее время единственной проблемой являетсячто объект неправильно оборачивается вокруг получаемых объектов ... Хотя я не уверен, что это вообще возможно.
Редактировать:
Я улучшилсистема также для переноса объектов, переданных в виде блоков:
def proxy__enwrap(obj)
isClass = obj.is_a?(Class)
oldClass = isClass ? obj : obj.class
sNewClass = "Proxy#{oldClass.to_s}"
code = <<-EOF
class #{sNewClass}
include InstanceProxy
def self.__cinit__(obj)
@@__cobj__ = obj
end
def self.__cget__
@@__cobj__
end
def self.to_ary
#fix for puts (puts calls to_ary. see: /6704898/ruby-pochemu-stavit-vyzov-toary)
[self.to_s]
end
def self.method_missing(m,*args,&block)
#Wrap block arguments:
newBlock = Proc.new {}
if block_given?
newBlock = Proc.new do |*args|
args = args.map {|arg| proxy__enwrap(arg)}
block.call(*args)
end
end
#Call delegated functions. Raise error if object doesn't respond to method.
#Return wrapped value
if @@__cobj__.respond_to? m
retVal = @@__cobj__.public_send(m,*args,*block)
return proxy__enwrap(retVal)
else
raise ArgumentError.new("Method '\#\{m.to_s}' doesn't exist.")
end
end
end
#{sNewClass}.__cinit__(#{oldClass.to_s})
if isClass
return #{sNewClass}
else
return #{sNewClass}.new(obj)
end
EOF
::Kernel.eval(code)
end
module InstanceProxy
def method_missing(m,*args,&block)
#Wrap block arguments:
newBlock = Proc.new {}
if block_given?
newBlock = Proc.new do |*args|
args = args.map {|arg| proxy__enwrap(arg)}
block.call(*args)
end
end
#Call delegated functions. Raise error if object doesn't respond to method.
#Return wrapped value
if @__obj__.respond_to? m
retVal = @__obj__.__send__(m,*args,&newBlock)
return proxy__enwrap(retVal)
else
raise ArgumentError.new("Method '#{m.to_s}' doesn't exist.")
end
end
def initialize(obj)
@__obj__ = obj
end
def to_ary
#fix for puts (puts calls to_ary. see: /6704898/ruby-pochemu-stavit-vyzov-toary)
[self.to_s]
end
end
#
XXApplication = Application
#Silence warnings of overwriting constant
original_verbosity = $VERBOSE
$VERBOSE = nil
::Object.const_set "Application", proxy__enwrap(Application)
$VERBOSE = original_verbosity