No commit activity in last 3 years
No release in over 3 years
Checksums method source and raises if upstream has changed.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.6
>= 0
>= 0

Runtime

 Project Readme

SafeMonkeypatch

Gem Version Build Status

If you can, please, DO NOT monkeypatch.

Sometimes I patch ActiveRecord, but ain't sure if it's gonna break in the next version of Rails. This gem would raise an error if monkey patched method has changed since last time you've adapted your patch to the upstream.

Simple usage

Assume some upstream in foo.gem:

class Foo
  def bar
    puts "do first thing"
    puts "do second thing"
    puts "do something else"
  end
end

And your code:

class Foo
  safe_monkeypatch :bar, md5: "", error: "patch for foo.gem v0.0.1"

  def bar
    puts "do first thing"
    # puts "do second thing" # don't do that
    puts "do something else"
  end
end

NOTE: do this BEFORE monkeypatch happens

You can also use any of Digest::*** checksum's methods: sha1 or even combine md5+sha1

Until upstream code isn't changed, it's working like usual. But if the new version changes the implementation of Foo#bar method, an error is raised while startup time (unless you monkeypatch in runtime, but now you're on your own):

SafeMonkeypatch::UpstreamChanged: Foo#bar expected to have md5 checksum: "", but has: ""
patch for foo.gem v0.0.1

Matching usage

Unfortunately, if you have to support different versions of foo.gem, you have to monkeypatch all the variant implementation. Use blocks for this:

class Foo
  safe_monkeypatch :bar, md5: 'some_checksum' do
    def bar
      "this works if upstream Foo#bar method has md5 of source equals 'some_checksum'
    end
  end

  safe_monkeypatch :bar, md5: 'another_checksum' do
    def bar
      "this works if upstream Foo#bar method has md5 of source equals 'another_checksum'
    end
  end
end

Note: if source of upstream change dramatically and you haven't such matching checksum, you won't notice this, as such use this method:

class Foo

  # NOTE: insert this BEFORE ANY monkeypatch: list all checksum variants
  safe_monkeypatch :bar, md5: ['some_checksum', 'another_checksum']

  safe_monkeypatch :bar, md5: 'some_checksum' do
    def bar
      "this works if upstream Foo#bar method has md5 of source equals 'some_checksum'
    end
  end

  safe_monkeypatch :bar, md5: 'another_checksum' do
    def bar
      "another patch"
      "this works if upstream Foo#bar method has md5 of source equals 'another_checksum'
    end
  end
end

Use block matching always this way. This will guarantee, that any of patches will be applied, or you'll get standard exception.

Advanced usage

You can also use it without patched module scope (for proper error use patched class/module name):

Foo.safe_monkeypatch Foo.instance_method(:bar), md5: 'invalid_checksum'

Happy monkeypatching :)