From: 7stud -- Date: 2011-04-17T03:20:50+09:00 Subject: Re: looking for an "inversion" pattern Kevin Mahler wrote in post #992945: > Fearless Fool wrote in post #992929: >> I'd like to create a method +foo+ that transforms: >> >> my_obj.foo.some_method(*args) >> >> to >> >> MyClass.some_method(my_obj, *args) > > class MyClass > def self.some_method(obj, *args) > puts "MyClass.some_method:" > puts "obj: #{obj.inspect}" > puts "args: #{args.inspect}" > end > end > > def define_foo(obj, clazz, method) > obj.singleton_class.class_eval do > define_method :foo do > Class.new do > define_method method do |*args| > clazz.send(method, obj, *args) > end > end.new > end > end > end > > my_obj = "my_obj thing" > args = [1,2,3] > define_foo(my_obj, MyClass, :some_method) > my_obj.foo.some_method(*args) > > # => > # MyClass.some_method: > # obj: "my_obj thing" > # args: [1, 2, 3] > > Returning facade or proxy objects like this can be an elegant solution > to certain problems. It's rather high on the abstraction ladder, though, > and without knowing the context I would wonder if more direct solutions > are possible. I don't know what's conceptually easier to understand, but in ruby there is no limit to how high you can stack singleton methods, e.g.: obj.foo obj.foo.some_method If obj.foo() returns obj's singleton class, then some_method() is being called as a class method of the singleton class. That means some_method is a method inside the singleton class's singleton class: obj's class ^ | | singleton2: some_method() ^ | | singleton1: foo() -> returns singleton1 ^ | | obj obj.foo.some_method And you can add as many singleton classes to the method lookup path as you want. For instance, if you have this call: obj.foo.some_method.do_stuff and obj.foo.some_method() returns singleton2, then do_stuff() is being called as a class method of singleton2, i.e. do_stuff() is a method in a parent class, singleton3, above singleton2. So in the original example at the top of the post, if the creating-a-new-anonymous-class-with-a-method-named-some_method-and-returning-an-instance-of-that-class is too hard to understand, you could do this: class MyClass def self.some_method(obj, *args) puts "MyClass.some_method:" puts "obj: #{obj.inspect}" puts "args: #{args.inspect}" end end def define_foo(obj, clazz, method) obj.singleton_class.class_eval do singleton = self define_method :foo do #Class.new do #define_method method do |*args| #clazz.send(method, obj, *args) #end #end.new #In here, self is equal to the obj that #will eventually call foo()--not obj.singleton_class. #Hence, the need to do singleton = self above. singleton.singleton_class.class_eval do define_method method do |*args| clazz.send(method, obj, *args) end end singleton #return the singleton class end end end my_obj = "my_obj thing" args = [1,2,3] define_foo(my_obj, MyClass, :some_method) my_obj.foo.some_method(*args) --output:-- MyClass.some_method: obj: "my_obj thing" args: [1, 2, 3] -- Posted via http://www.ruby-forum.com/.