From: "Jesús Gabriel y Galán" Date: 2009-11-20T03:20:20+09:00 Subject: Re: Re-opening an existing module and changing a method 2009/11/19 Jesús Gabriel y Galán : > On Thu, Nov 19, 2009 at 6:27 PM, Aldric Giacomoni wrote: >> "I hear and I forget; I see and I remember; I do and I understand." >> Wouldn't it be nice if it were that simple - clearly they did not know >> about the subtle art of debugging. >> >> So, I'm trying to hack at the math module. >> Expected: >>>> Math.sqrt(2) >> => sqrt(2) >> Actual result, mileage does not vary: >>>> Math.sqrt(2) >> => 1.4142135623731 >> >> require 'mathn' >> module Math >>  alias :old_sqrt :sqrt >>  def sqrt x >>    result = old_sqrt x >>    if result.is_a? Float >>      "sqrt(#{x})" >>    else >>      result >>    end >>  end >> end >> >> puts Math.sqrt(2) >> >> I had originally not attempted an alias, I just did "result = super x" >> but it didn't really amount to much, either. >> Where am I thinking about this wrong? > > The problem is that mathn is using the module_function method to > convert sqrt into an method of the Math module. > According to http://ruby-doc.org/core/classes/Module.src/M001642.html: > > "Module functions are copies of the original, and so may be changed > independently" > > So I think you are not redefining the module function, but the > original, which doesn't have any effect when you call Math.sqrt (this > is calling the version created by module_function). Doing this: > > irb(main):042:0> module Math > irb(main):043:1> def sqrt x > irb(main):044:2> result = super x > irb(main):045:2> p [result, result.class] > irb(main):046:2> result > irb(main):047:2> end > irb(main):048:1> module_function :sqrt > irb(main):049:1> end > => Math > irb(main):050:0> Math.sqrt 2 > NoMethodError: super: no superclass method `sqrt' >        from (irb):44:in `sqr > > allows you to actually override the version created by > module_function, but I don't know how to then call the original, since > neither the original alias you had nor super are working. But maybe > this points you in the right direction. Got it: irb(main):001:0> require 'mathn' => true irb(main):002:0> module Math irb(main):003:1> class << self irb(main):004:2> alias :old_sqrt :sqrt irb(main):005:2> end irb(main):006:1> def sqrt x irb(main):007:2> result = old_sqrt x irb(main):008:2> p [result, result.class] irb(main):009:2> result irb(main):010:2> end irb(main):011:1> module_function :sqrt irb(main):012:1> end => Math irb(main):013:0> Math.sqrt 2 [1.4142135623731, Float] => 1.4142135623731 Jesus.