Created
June 22, 2012 13:53
-
-
Save anklos/2972858 to your computer and use it in GitHub Desktop.
hooks
This file contains hidden or 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
#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