Forum: Ruby unalias a method?

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.
13b511cd4fff9f72326e38526b9701fa?d=identicon&s=25 Todd Burch (toddburch)
on 2009-01-25 14:50
I needed to alias a method (alias_method) to change its behavior during
a series of tests the other day.  I was able to alias the Module's
method ok, but I couldn't figure out how to unalias it when I was done.

What's the technique to unalias a method that has been aliased?

Thanks.
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2009-01-25 15:42
Todd Burch wrote:
>
> What's the technique to unalias a method that has been aliased?
>

class Foo
  def hello
    p "hi"
  end
  alias_method :hello2, :hello
end

Foo.new.hello2  #=> "hi"
class Foo
  remove_method :hello2
end
Foo.new.hello2  #=> undefined method `hello2'
13b511cd4fff9f72326e38526b9701fa?d=identicon&s=25 Todd Burch (toddburch)
on 2009-01-25 20:57
Mike Gold wrote:
>
> class Foo
>   def hello
>     p "hi"
>   end
>   alias_method :hello2, :hello
> end
>
> Foo.new.hello2  #=> "hi"
> class Foo
>   remove_method :hello2
> end
> Foo.new.hello2  #=> undefined method `hello2'

Thanks Mike.  Perhaps that's what I said, but that's not what I meant...
;)   Sorry about that.   I tried recreating my scenario with
alias_method, and it seems as if it wasn't really a factor in my test.

This is the sequence that I would like to happen:

module Foo
  def Foo.hello
    p "Hi"
  end
end  # module

####################

p "I expect to print hi:"
Foo.hello                 #<== this works

####################

module Foo
  def Foo.hello
    p "printing of hi is suppressed"
  end
end

####################

p "I expect to suppress printing of hi:"
Foo.hello               # <== this works

####################

p "Now, I want to print hi again:"

###??? What needs to happen here?

Foo.hello


I'm assuming that alias_method is what I need to be using to temporarily
"redirect" all my Foo.hello calls to do something different for a
certain period of time, and finally I want to revert to the original
behavior of Foo.hello.

I used a module example, because that's what I'm using my real case, and
I don't have access to the module source.

Thanks, Todd
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-01-25 21:36
(Received via mailing list)
On Sun, Jan 25, 2009 at 2:55 PM, Todd Burch <promos@burchwoodusa.com>
wrote:

> I'm assuming that alias_method is what I need to be using to temporarily
> "redirect" all my Foo.hello calls to do something different for a
> certain period of time, and finally I want to revert to the original
> behavior of Foo.hello.
>
> I used a module example, because that's what I'm using my real case, and
> I don't have access to the module source.

Hopefully this does what you'd expect.  -greg

module Foo
  extend self

  def hello
    p "Hi"
  end
end

Foo.hello

module Foo
  alias_method :old_hello, :hello

  def hello
    p "Hello again"
  end
end

Foo.hello

module Foo
  alias_method :hello, :old_hello
end

Foo.hello
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-01-25 21:56
(Received via mailing list)
On Jan 25, 2009, at 05:48 , Todd Burch wrote:

> What's the technique to unalias a method that has been aliased?

alias the old method back. A really messy example of this is heckle
where we replace methods over and over and then alias the original
back into place.
13b511cd4fff9f72326e38526b9701fa?d=identicon&s=25 Todd Burch (toddburch)
on 2009-01-25 23:16
>
> Hopefully this does what you'd expect.  -greg
>

Hey Greg!  That works great from Terminal - thanks.

I changed your example to work with Sketchup, and by writing it like
this, I got it work under Sketchup as I want:

(The UI.messagebox put up a dialog box, similar to  a javascript alert()
box )

require 'sketchup.rb' ;
include UI   # <== this is the key to getting this to work

messagebox "Regular Messagebox..." ;

module UI
  extend self
  alias_method :messagebox_old, :messagebox

  def messagebox (string)
    puts "aliased method: #{string}"
  end
end

messagebox "this should show up in the console" ;

module UI
  alias_method :messagebox, :messagebox_old
end

messagebox "Back to normal" ;

In the above case, I get a popup, then a message to the Ruby console,
then a popup.  Perfect.
However, from all my code, I typically never "include UI" and write
scripts like thi, qualifying the messagebox method with UI.messagebox...

require 'sketchup.rb' ;

UI.messagebox "Regular Messagebox..." ;

module UI
  extend self
  alias_method :messagebox_old, :messagebox

  def messagebox (string)
    puts "aliased method: #{string}"
  end
end

UI.messagebox "this should show up in the console" ;

module UI
  alias_method :messagebox, :messagebox_old
end

UI.messagebox "Back to normal" ;


Adding the UI. qualifier, the aliased method is never called and I get 3
popups.
Any ideas?
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2009-01-26 00:37
Todd Burch wrote:
>
> I'm assuming that alias_method is what I need to be using to temporarily
> "redirect" all my Foo.hello calls to do something different for a
> certain period of time, and finally I want to revert to the original
> behavior of Foo.hello.
>

In that case, maybe push/pop would make things easier.

module MethodStack
  class << self
    def included(includer)
      stack = Hash.new

      define_method(:push_method) { |method_name, &block|
        unless stack.has_key?(method_name)
          stack[method_name] = [instance_method(method_name)]
        end
        stack[method_name].push(block)
        define_method(method_name, &block)
      }

      define_method(:pop_method) { |method_name|
        stack[method_name].pop
        define_method(method_name, stack[method_name].last)
      }
    end
  end
end

class Foo
  class << self
    include MethodStack
  end
  def hello
    p "original hello"
  end
end

obj = Foo.new
obj.hello # => "original hello"

class Foo
  push_method(:hello) {
    p "replacement hello"
  }
end

obj.hello # => "replacement hello"
Foo.pop_method(:hello)
obj.hello # => "original hello"
13b511cd4fff9f72326e38526b9701fa?d=identicon&s=25 Todd Burch (toddburch)
on 2009-01-26 01:56
Mike Gold wrote:

>
> In that case, maybe push/pop would make things easier.
>

Didn't work.


todd-burchs-computer:myruby toddburch$ ruby pushpop.rb
pushpop.rb:6: syntax error, unexpected tAMPER, expecting '|'
      define_method(:push_method) { |method_name, &block|
                                                   ^
pushpop.rb:12: syntax error, unexpected '}', expecting kEND
      }
       ^
todd-burchs-computer:myruby toddburch$
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2009-01-26 02:29
Todd Burch wrote:
> Mike Gold wrote:
>
>>
>> In that case, maybe push/pop would make things easier.
>>
>
> Didn't work.
>
>
> todd-burchs-computer:myruby toddburch$ ruby pushpop.rb
> pushpop.rb:6: syntax error, unexpected tAMPER, expecting '|'
>       define_method(:push_method) { |method_name, &block|
>                                                    ^
> pushpop.rb:12: syntax error, unexpected '}', expecting kEND
>       }
>        ^
> todd-burchs-computer:myruby toddburch$

The |&block| syntax is supported on 1.8.7+.  Rewriting MethodStack for
1.8.6 is left as an exercise.
13b511cd4fff9f72326e38526b9701fa?d=identicon&s=25 Todd Burch (toddburch)
on 2009-01-26 02:54
Mike Gold wrote:
>
> The |&block| syntax is supported on 1.8.7+.  Rewriting MethodStack for
> 1.8.6 is left as an exercise.

I had to laugh out loud on that one.  Thanks Mike!
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2009-01-26 15:50
Todd Burch wrote:
> Mike Gold wrote:
>>
>> The |&block| syntax is supported on 1.8.7+.  Rewriting MethodStack for
>> 1.8.6 is left as an exercise.
>
> I had to laugh out loud on that one.  Thanks Mike!

My last comment sounded more glib than intended.  Since I've already
used MethodStack in my own code, I think it can be generally useful in
cleaning up repetitive alias_method calls.

I might try submitting it to facets, with two changes: change names to
push_instance_method/pop_instance_method for symmetry with
Module#instance_method, and add 1.8.6 compatibility.
This topic is locked and can not be replied to.