Home Home > 2011 > 03 > 18 > Temporary overwrite method for specific task
Sign up | Login

Deprecation notice: openSUSE Lizards user blog platform is deprecated, and will remain read only for the time being. Learn more...

Temporary overwrite method for specific task

March 18th, 2011 by

Hi,
today I must solve issue with not well structured code. Problem is that one method return last correct version, but in one specific case it needs to return newest version (even incorrect). There is many calls between top level method which know what needs to call and target method which is called from generic code. Now I need to fix it and code is not well tested and quite sensitive to changes ( this fix is fix of another fix :). So what is the safest way to change it?
I decide that the best solution which doesn’t change almost nothing ( but is suitable just for maintenance update, for trunk I create better solution ) is temporary overwrite of target method to change its behavior. Now how to do it?
There is simple example:

class T
  def test
    puts "test"
  end

  def lest
    puts "lest"
  end

  def m
    test
  end
end


T.new.m
T.send(:define_method,:m_a) { lest }
T.send(:alias_method, :m_old, :m)
T.send(:alias_method, :m, :m_a)
T.new.m
T.send(:alias_method, :m, :m_old)
T.send(:undef_method, :m_a)
T.send(:undef_method, :m_old)
T.new.m

as you can see after modification class is exact same as before ( except if there is method a, but it is possible to handle it via introspection and dynamic choose of method). I don’t need to change whole stack of calls to add parameter or introduce new singleton class which can have flag.
I hope it help someone with his fix of not so well written piece of software.

Both comments and pings are currently closed.

2 Responses to “Temporary overwrite method for specific task”

  1. I did something almost identical: https://github.com/mvidner/ruby-dbus/blob/9384f5e4284bb3bff722eeebe28c7d160173e781/test/t6-loop.rb#L22

    The difference is that I needed to patch a single object, so I used class << @obj, def, alias, remove_method.

    Hmm, this is significant if T#m exists in a superclass: http://www.nach-vorne.de/2008/2/28/undef_method-remove_method/index.html

    • Josef Reidinger

      Yes, looks similar. Of course you have advantage that you edit just one object, so your solution is multithread. My change affect all threads. Remove_method versus undef_method depends on your goal. Just one note to your solution.
      Remove :wait_for_message and then realias it is useles. You can just call alias and if you want cleaning, you can remove orig version ( or there is sufficient just undef ).