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.
Todd B. (Guest)
on 2009-01-25 15: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.
Mike G. (Guest)
on 2009-01-25 16:42
Todd B. 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'
Todd B. (Guest)
on 2009-01-25 21:57
Mike G. 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
Gregory B. (Guest)
on 2009-01-25 22:36
(Received via mailing list)
On Sun, Jan 25, 2009 at 2:55 PM, Todd B. <removed_email_address@domain.invalid>
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
Ryan D. (Guest)
on 2009-01-25 22:56
(Received via mailing list)
On Jan 25, 2009, at 05:48 , Todd B. 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.
Todd B. (Guest)
on 2009-01-26 00: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?
Mike G. (Guest)
on 2009-01-26 01:37
Todd B. 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"
Todd B. (Guest)
on 2009-01-26 02:56
Mike G. 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$
Mike G. (Guest)
on 2009-01-26 03:29
Todd B. wrote:
> Mike G. 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.
Todd B. (Guest)
on 2009-01-26 03:54
Mike G. 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!
Mike G. (Guest)
on 2009-01-26 16:50
Todd B. wrote:
> Mike G. 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.