Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Ensures your extensions and monkey patches don't redefine existing methods as well as get redefined by others.
Ruby
branch: master

This branch is 1 commit ahead of wegowise:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.travis.yml
CHANGELOG.txt
LICENSE.txt
README.md
Rakefile
watchdog.gemspec

README.md

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  NOOOOO...

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

Something went wrong with that request. Please try again.