Skip to content

Instantly share code, notes, and snippets.

@danielberlinger
Created June 10, 2011 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielberlinger/47cd6a3a1dc198fd033b to your computer and use it in GitHub Desktop.
Save danielberlinger/47cd6a3a1dc198fd033b to your computer and use it in GitHub Desktop.
Hooks pattern
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