Forum: Ruby Method equality; setting instance variables on Method instan

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2006-12-24 18:26
(Received via mailing list)
A few questions about the code below:
1) Why do m1 and m2 have different IDs but compare as equal?
2) Why does m2 invoke the same old functionality when run?
3) Why did my instance_variable_set not 'take'?

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
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2006-12-24 21:26
(Received via mailing list)
Phrogz wrote:
> A few questions about the code below:
> 1) Why do m1 and m2 have different IDs but compare as equal?
> 2) Why does m2 invoke the same old functionality when run?
> 3) Why did my instance_variable_set not 'take'?

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.
This topic is locked and can not be replied to.