Module to make guerilla (monkey?) / reopening classes easier

I hammered this out today. It has some limitations (works only for
classes, not modules), and when using the block only form of patch
your method redefinitions are evaluated twice. I’m looking for
commentary before I take the step of writing some testcases and
packaging it up for human consumption:

Usage:

class A
def b(x, y)
x + y
end
end
a = A.new

require ‘patch’

class A
include Patchable
end

A.patch(:b) do |y|
hyper(1, y) # I only ever call b with an x argument of 1
end

a.b(5)
#=> 6

class B
def foof
yield
end
end

class B
include Patchable
end

B.patch do
def foof
hyper { yield + 1 }
end
end

b = B.new
b.foof { 3 }
#=> 4

And heres the code:

patch.rb:

module Patchable
module ClassMethods
def patch(method_name = nil, &new_body)
if method_name
method_name = method_name.to_sym
pre_patched_versions[method_name] = instance_method
(method_name)
define_method(method_name, &new_body)
else
klass = Class.new
imeths = klass.instance_methods
klass.class_eval(&new_body)
new_meths = klass.instance_methods - imeths
new_meths.each do |m|
pre_patched_versions[m.to_sym] = instance_method(m)
end
class_eval(&new_body)
end
self
end

 def pre_patched_versions
   @pre_patched_versions ||= {}
 end

end

def hyper(*args, &block)
meth_name = caller[0][/`([^’]+)’/, 1].to_sym
self.class.pre_patched_versions[meth_name].bind(self).call
(*args, &block)
end

def self.included(other)
other.extend(ClassMethods)
end
end

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs