Skip to content

Instantly share code, notes, and snippets.

@duncanbeevers
Created January 3, 2012 23:08
Show Gist options
  • Save duncanbeevers/1557465 to your computer and use it in GitHub Desktop.
Save duncanbeevers/1557465 to your computer and use it in GitHub Desktop.
Augmenting an instance with methods defined in a helper module
class Loop
attr_accessor :name
def initialize name
self.name = name
end
end
module LoopDecoratorHelper
def loop_delete_link loop
"Delete #{loop.name}"
end
def frog_breath
"Disgusting"
end
end
module HelperAugmenter
class << self
def augment mod, prefix, instance
curry_mod = Module.new
carrier = Class.new
carrier.extend mod
matcher = /^#{Regexp.quote(prefix)}_(.*)$/
matching_methods = mod.instance_methods.select do |method_name|
method_name.to_s.match(matcher)
end.each do |method_name|
curried_method_name = method_name.to_s.match(matcher)[1]
curry_mod.instance_eval do
define_method curried_method_name do
carrier.method(method_name).call(instance)
end
end
end
instance.extend(curry_mod)
end
end
end
require 'test/unit'
require './augment'
class LoopDecoratorHelperTest < Test::Unit::TestCase
def test_loop_name
assert Loop.new('hi').name == 'hi'
end
def test_augment_preserves_methods
loop = Loop.new('oranges')
HelperAugmenter.augment LoopDecoratorHelper, 'loop', loop
assert loop.name == 'oranges'
end
def test_augment_adds_methods
loop = Loop.new('apples')
HelperAugmenter.augment LoopDecoratorHelper, 'loop', loop
assert loop.delete_link == "Delete apples"
end
def test_augment_does_not_add_non_matching_methods_or_original_helper_methods
loop = Loop.new('bananas')
HelperAugmenter.augment LoopDecoratorHelper, 'loop', loop
assert !loop.respond_to?(:loop_delete_link)
assert !loop.respond_to?(:frog_breath)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment