Description

Watchdog ensures your extensions and monkey patches don't redefine existing methods as well as get redefined by others.

Install

$ gem install watchdog

Usage

Let's say we want to add an instance method to String with extension module ToDate:

module ToDate
  def to_date
    Date.parse(self)
  end
end

String.send :include, ToDate

What happens if String#to_date already exists? What happens if another gem redefines that method later? Breakage.

Watchdog watches over these concerns with a simple extend:

module ToDate
  extend Watchdog

  def to_date
    Date.parse(self)
  end
end

String.send :include, ToDate

Now if String#to_date already exists, watchdog raises a runtime error. Same goes if someone tries to redefine the method later:

>> class String; def to_date; p 'HAHAHA'; end; end
Watchdog::ExtensionMethodExistsError: Date not allowed to redefine extension method from ToDate#to_date
    ./lib/watchdog.rb:13:in `guard'
    ./lib/watchdog/german_shepard.rb:23:in `method_added'
    (ripl):3

Watchdog also guards over extension modules that define class methods:

module DaysTillXmas
  extend Watchdog

  def days_till_xmas
    Date.new(Date.today.year, 12, 25) - Date.today
  end
end

Date.extend DaysTillXmas
# Date.days_till_xmas ->  253  NOOOO...

Caveats

Watchdog's protectiveness can be problematic with mocks in a test suite as they love to redefine methods. Watchdog provides Watchdog.sleep, a Proc to conditionally turn off guarding extension methods. By default, Watchdog sets this so that Rspec mocks are allowed to slip by:

Watchdog.sleep = lambda { defined? RSpec && !caller.grep(/rspec-mocks/).empty? }

Credits

Thanks to Wegowise for open-source time to make this possible!

License

See LICENSE.txt