-
-
Save danielberlinger/47cd6a3a1dc198fd033b to your computer and use it in GitHub Desktop.
Hooks pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module HooksForThisUse | |
def before_handle_print_it(*args) | |
p "About to run #{self} with #{args.inspect}" | |
end | |
def after_handle_print_it_again(*args) | |
p "Already ran #{self} with #{args.inspect}" | |
end | |
def on_failure_print_it_one_more_time(*args) | |
p "That utterly failed #{self} with #{args.inspect}" | |
end | |
end | |
module Hookifier | |
def self.included(klass) | |
klass.extend ::Hookifier::ClassMethods | |
end | |
module ClassMethods | |
# | |
# Takes a splat of method names, and wraps them with "wrap_hooks_around_it". | |
# | |
def hooked_methods(*methods) | |
methods.each do |meth| | |
m = instance_method meth | |
define_method meth do |*args| | |
wrap_hooks_around_it m.bind(self), *args | |
end | |
end | |
end | |
end | |
def wrap_hooks_around_it(method, *args) | |
before_hooks = self.methods.grep(/^before_handle/).sort | |
after_hooks = self.methods.grep(/^after_handle/).sort | |
failure_hooks = self.methods.grep(/^on_failure/).sort | |
begin | |
begin | |
before_hooks.each do |hook| | |
self.send(hook, *args) | |
end | |
rescue Exception => e | |
#Exit gracefully? p "#{e}" | |
return false | |
end | |
#do stuff here | |
method[*args] | |
#if exception are raise while "doing", these hooks will never run. | |
begin | |
after_hooks.each do |hook| | |
self.send(hook, *args) | |
end | |
rescue Exception => e | |
#Exit gracefully? p "#{e}" | |
return false | |
end | |
# If an exception occurs during the execution, look for an | |
# on_failure hook then re-raise. | |
rescue Object => e | |
failure_hooks.each { |hook| self.send(hook, e, *args) } | |
raise e | |
end | |
end | |
end | |
class TestThing | |
include Hookifier | |
include HooksForThisUse | |
def initialize(full_url, username = nil, password = nil) | |
@full_url = full_url | |
@username = username | |
@password = password | |
end | |
def call_remote_service(*args) | |
p "remote service called with args: #{args.inspect}" | |
end | |
def call_remote(*args) | |
raise "crap" | |
end | |
hooked_methods :call_remote_service, :call_remote | |
end | |
t = TestThing.new("somewhere") | |
t.call_remote_service("daniel", :args) | |
t.call_remote(:more_args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment