Gary Wright
11/7/2007 9:33:00 PM
On Nov 7, 2007, at 3:04 PM, Adam Anderson wrote:
> I want any method to implicitly check the scope of the class in which
> the method is being called and *THEN* check the scope outside the
> class.
> This is just an exercise in making code more readable and require less
> typing, as far I am concerned.
I think what you are suggesting is the ability to queue up a number
of objects to be used as 'self' while a block is being evaluated. If
none of the objects can handle a message, then the process would
be repeated this time looking for method_missing().
Something like:
also_eval(a,b,c) { #code }
So the code would be executed with the 'normal' self. If a method
was not found it would be searched for via object a then b then c.
The main problem with implementing this is that you really want to
insert a step between the normal method lookup and method_missing and
I don't think that can be done without using method_missing itself.
Anyway, here is a solution that uses method_missing to link the
objects. The last object in the chain is responsible for doing
something via its own method_missing. This solution will not
properly handle nested blocks due the limitations on define_method().
I'm sure this could be improved. I'm not sure how useful this is
but it was a fun problem to think through.
module Kernel
def also_eval(*args, &block)
block_self = eval "self", block.binding
args.inject(block_self) { |op1, op2|
(class <<op1; self; end).send(:define_method, :method_missing)
{ |*args|
begin
op2.send(*args)
rescue NoMethodError
begin
super
rescue NoMethodError
op2.send(:method_missing, *args)
end
end
}
op2
}
block.call
end
end
class A
also_eval({:a=>1}, [100,200]) {
p self # A
p keys # the hash
p first # the array
p bogus # not found
}
end