Last active
May 30, 2018 17:47
-
-
Save sancarn/d84a76e36a94c8dbcb5244caede45bd0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Application | |
| def self.open_current | |
| return Current.new() | |
| end | |
| end | |
| class Current | |
| def get_row(row) | |
| Row.new(row) | |
| end | |
| end | |
| class Row | |
| def get_col(row) | |
| #... | |
| end | |
| end | |
| =begin | |
| DEFINITION: | |
| I want a simple wrapper which will wrap the Application class and down. | |
| Criterium: | |
| * Each class must be extendable directly via the proxy class: | |
| class ProxyApplication | |
| def method() | |
| #... | |
| end | |
| end | |
| class ProxyCurrent | |
| def method() | |
| #... | |
| end | |
| end | |
| #... | |
| * All methods of delegated class should be accessible from Proxy<<Class>> | |
| * No proxy class can be predefined, new instances are created on-the-fly. | |
| * All methods of proxy class should return proxied objects,i.e. | |
| ProxyApplication.open_current #=> ProxyCurrent instance | |
| #<ProxyCurrent>.get_row(1) #=> ProxyRow instance | |
| #... | |
| * Must not call the initialisation methods of the classes themselves. | |
| * Ideally would work even if within console | |
| =end | |
| #class Proxy | |
| # def initialize(obj) | |
| # | |
| # end | |
| #end | |
| class Proxy < SimpleDelegator | |
| def initialize(obj) | |
| # #Work around for | |
| @delegate_class = (obj.is_a? Class) ? obj : obj.class | |
| super(obj) | |
| end | |
| def to_s | |
| #Define to_s to show that class is proxied | |
| #return "PROXY:" + @delegate_class.to_s | |
| end | |
| def method_missing(m,*args,&block) | |
| begin | |
| #Try to get return value from class method | |
| retVal = @delegate_class.__send__(m,*args,&block) | |
| rescue | |
| #Get return value from instance method if available | |
| retVal = super.__send__(m,*args,&block) | |
| end | |
| #Enwrap return value | |
| return Proxy.enwrap(retVal) | |
| end | |
| def Proxy.enwrap(retVal) | |
| #Extension class name | |
| newClassName = "Proxy" + retVal.class.to_s | |
| if !(::Object.constants.include?(newClassName.to_sym)) | |
| #Define a class dynamically | |
| classDef = ::Object.const_set newClassName, Class.new(Proxy) | |
| else | |
| classDef = ::Object.const_get(newClassName.to_sym) | |
| end | |
| #Return new instance of retVal | |
| return classDef.new(retVal) | |
| end | |
| end | |
| =begin ::OLD CODE:: | |
| Proxy.enwrap: | |
| classDef = <<-EOF | |
| class #{newClassName} < Proxy | |
| end | |
| return #{newClassName}.new(retVal) | |
| EOF | |
| return eval(classDef) | |
| Initialize: | |
| @delegate_class.singleton_methods.each do |name| | |
| self.class.send(:define_method,name) do |*args| | |
| retVal = @delegate_class.__send__(name, *args) | |
| return Proxy.enwrap(retVal) | |
| end | |
| end | |
| =end | |
| #---------------------------------------------------------------------- | |
| # TEST SCRIPT | |
| #---------------------------------------------------------------------- | |
| PApplication = Proxy.new(Application) | |
| puts PApplication | |
| current = PApplication.open_current() | |
| puts current | |
| #Try to extend ProxyApplication and ProxyCurrent. | |
| class ProxyApplication | |
| def self.test() | |
| return true | |
| end | |
| end | |
| class ProxyCurrent | |
| def test() | |
| return true | |
| end | |
| end | |
| puts PApplication.test() | |
| puts current.test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment