I suspect all answers have something to do with where the methods are
being defined/shadowed, but I'll be damned if I can figure them out.
slim:~/Desktop/test gavinkistner$ ls -Flag
total 8
drwxr-xr-x 3 staff 102 Dec 24 10:15 ./
drwx------ 34 staff 1156 Dec 24 10:15 ../
-rw-r--r-- 1 staff 734 Dec 24 10:20 override.rb
slim:~/Desktop/test gavinkistner$ cat override.rb
class Module
def override( method_name, &block )
orig_method = method( method_name )
new_name = "m#{rand(1000000000)}"
alias_method new_name, method_name
define_method( method_name, &block )
method( method_name ).instance_variable_set( :@__orig_method_name,
new_name )
end
def restore( method_name )
alias_method method_name, method( method_name
).instance_variable_get( :@__orig_method_name )
end
end
m1 = Kernel.method( :system )
system 'ls'
Kernel.override( :system ){ |code| puts "`#{code}` not allowed"}
m2 = Kernel.method( :system )
system 'ls'
p m1, m2, m1==m2, m1.object_id, m2.object_id
m1.call( 'ls' )
m2.call( 'ls' )
Kernel.restore( :system )
m3 = Kernel.method( :system )
system 'ls'
__END__
slim:~/Desktop/test gavinkistner$ ruby override.rb
override.rb
`ls` not allowed
#<Method: Kernel.system>
#<Method: Kernel.system>
true
953400
953250
override.rb
override.rb
override.rb:11:in `alias_method': nil is not a symbol (TypeError)
from override.rb:11:in `restore'
from override.rb:26
Another data point on that last question: at least it looks like you
can set/get instance variables on a Method instance in general:
irb(main):001:0> m1 = Kernel.method( :system )
=> #<Method: Kernel.system>
irb(main):002:0> m1.instance_variable_set( :@foo, :bar )
=> :bar
irb(main):003:0> m1.instance_variables
=> ["@foo"]
irb(main):004:0> m1.instance_variable_get( :@foo )
=> :bar
In case it wasn't obvious, what I am trying to achieve with the above
code is a stack-like method override/restore system. Each time you
override a method, the method should store the name of the
randomly-chosen alias for the old method.
A workaround will be to store the stack of method names on the module
itself (which I'll try next); nonetheless, I'm interested in why my
original code didn't work as I expected.