10

I am trying to find a way that I can override a method, do something, and then revert without leaving any artifacts around.

I have implemented this using mocha but obviously this is not going to fly in a production app. Notice the new method has parameters and the old one does not.

Example as follows

require 'rubygems'
require 'mocha'

class Example

  def to_something
    self.stubs(:attribs => other(1))
    r = attribs_caller
    self.unstub(:attribs)
    r
  end

  def other(int)
    {"other" => int }
  end

  def attribs_caller
    attribs
  end

  def attribs
    {"this" => 1 }
  end

end

a1 = Example.new

puts a1.attribs_caller  #=> this1
puts a1.to_something    #=> other1
puts a1.attribs_caller  #=> this1
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
stellard
  • 5,162
  • 9
  • 40
  • 62

2 Answers2

11
class String
  alias orig_reverse reverse
  def reverse(n)
    'fooled you. '*n
  end
end

puts "ab".reverse(2)
#=> fooled you fooled you

# clean up:
class String
  alias reverse orig_reverse
  remove_method(:orig_reverse)
end

puts "ab".reverse #=> ba
steenslag
  • 79,051
  • 16
  • 138
  • 171
  • nice, one issue with this is the fact that the new method is dynamic and requires some params. I could define this method dynamically however. I updated the example to reflect this. – stellard Apr 20 '11 at 18:28
  • Looks like the correct parameter ordering is `alias alias_name original_name`, not the other way around... – deprecated Oct 07 '13 at 06:22
3

Another way to do that, without creating an extra method, is this:

class Foo
  def bar
    :old_method
  end
end

Foo.new.bar # => :old_method

$old_method = Foo.new.method(:bar)

class Foo
  def bar
    :new_method
  end
end

Foo.new.bar # => :new_method

class Foo
  define_method($old_method.name, &$old_method)
end

Foo.new.bar # => :old_method

I think that this is better than using an alias method. In Ruby methods are, also, objects. I just take the reference of the object before destructing the association of the object (the method) with the class. After I add the same method. It also works if you use the undef keyword to remove the method from the class. The bad point is that you have to have an object of the class to take the reference of the method.

bragboy
  • 34,892
  • 30
  • 114
  • 171
Guilherme Bernal
  • 8,183
  • 25
  • 43