The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Monkey patching and aliases

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Daniel Berger

Posts: 1383
Nickname: djberg96
Registered: Sep, 2004

Daniel Berger is a Ruby Programmer who also dabbles in C and Perl
Monkey patching and aliases Posted: Oct 27, 2006 11:30 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Daniel Berger.
Original Post: Monkey patching and aliases
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Daniel Berger
Latest Posts From Testing 1,2,3...

Advertisement
Although Ruby's open classes are a powerful feature, there is one (well, at least one) gotcha to watch out for - aliases. You see, aliases don't survive method redefinition. Consider the following code:
class Foo
   def bar
      puts "hello"
   end
   alias baz bar
end

Foo.new.bar => 'hello'
Foo.new.baz => 'hello'

Ok, works as expected. Now, let's reopen the class and redefine the 'bar' method:
class Foo
   def bar
      puts "goodbye"
   end
end

Foo.new.bar => 'goodbye'
Foo.new.baz => 'hello'

Whoops! Our alias doesn't survive the monkey patching!

Is it possible to have an alias survive monkey patching? Not really. The main issue is something I brought up on ruby-talk:196740 - there just isn't an easy way to determine a list of aliases for a given class because Ruby doesn't store that data internally. Ryan Davis did post a potential solution using RubyInline that was quite impressive but quite ugly.

What if we patch Ruby so that classes *did* store that sort of information? Perhaps in Object. Then we could use Module#method_added for something like this:
class Foo   
   def method_added(id)
      if self.aliased_methods.include?(id.id2name)
         self.aliased_methods.each{ |a|
            alias a id.id2name if a == id.id2name
         }  
      end
   end
end

With that in place whenever you redefined an existing method the aliases for that method would be remapped automatically.

On the other hand, maybe you don't want that behavior. In fact, you could argue that the alias provides you with a handy way to get back at the original behavior if and when you want to:
class Foo
   def bar
      baz # Execute the orignal bar method
      ... # Extra stuff for our custom bar method
   end
end

With that in mind, we could abstract this by altering the 'alias' keyword to accept an optional third argument. The third argument would let us declare whether or not an alias should automatically remap itself whenever its aliased method was monkey patched:
class Foo
   def test
      puts "this is a test'
   end
   alias test2 test true   # Remaps aliases when monkey patched
   alias test3 test false  # Does not remap aliases
end

Foo.new.test  => 'this is a test'
Foo.new.test2 => 'this is a test'
Foo.new.test3 => 'this is a test'

class Foo
   def test
      puts "something changed"
   end
end

Foo.new.test  => 'something changed'
Foo.new.test2 => 'something changed'
Foo.new.test3 => 'this is a test'

On a side note, maybe this could be better accomplished with annotations somehow.

Read: Monkey patching and aliases

Topic: Mongrel / Rails Denial of Service Vunerability Previous Topic   Next Topic Topic: MVC and Rails

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use