Skip to content

Instantly share code, notes, and snippets.

@anklos
Created June 22, 2012 13:53
Show Gist options
  • Save anklos/2972858 to your computer and use it in GitHub Desktop.
Save anklos/2972858 to your computer and use it in GitHub Desktop.
hooks
#borrow from https://github.com/apotonick/hooks
#changes:
#remove block call support
#extend ActiveSupport::Concern into module to support nested module dependency
#add ability to pass multiple call_back methods params to a trigger
#for example: after_failed :job1, :job2..
require 'active_support/concern'
module Hooks
module InheritableAttribute
# Creates an inheritable attribute with accessors in the singleton class. Derived classes inherit the
# attributes. This is especially helpful with arrays or hashes that are extended in the inheritance
# chain. Note that you have to initialize the inheritable attribute.
#
# Example:
#
# class Cat
# inheritable_attr :drinks
# self.drinks = ["Becks"]
#
# class Garfield < Cat
# self.drinks << "Fireman's 4"
#
# and then, later
#
# Cat.drinks #=> ["Becks"]
# Garfield.drinks #=> ["Becks", "Fireman's 4"]
def inheritable_attr(name)
instance_eval %Q{
def #{name}=(v)
@#{name} = v
end
def #{name}
return @#{name} unless superclass.respond_to?(:#{name}) and value = superclass.#{name}
@#{name} ||= value.clone # only do this once.
end
}
end
end
end
module Hooks
extend ActiveSupport::Concern
def self.included(base)
base.extend InheritableAttribute
base.extend ClassMethods
end
module ClassMethods
def define_hook(name)
accessor_name = "_#{name}_callbacks"
setup_hook_accessors(accessor_name)
define_hook_writer(name, accessor_name)
end
def run_hook(name, *args)
run_hook_for(name, self, *args)
end
def run_hook_for(name, scope, *args)
callbacks_for_hook(name).each do |callback|
scope.send(callback, *args)
end
end
def callbacks_for_hook(name)
send("_#{name}_callbacks")
end
private
#get all the call_back methods name
#for example, after_falied :job1, :job2
#so it will create instance _after_failed_call_backs = [:job1, :job2]
def define_hook_writer(hook, accessor_name)
instance_eval %Q{
def #{hook}(*methods)
methods.each do |m|
#{accessor_name} << m
end
end
}
end
def setup_hook_accessors(accessor_name)
inheritable_attr(accessor_name)
send("#{accessor_name}=", []) # initialize ivar.
end
end
def run_hook(name, *args)
self.class.run_hook_for(name, self, *args)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment