Last active
September 15, 2017 11:22
-
-
Save igorkasyanchuk/7972080816fffc86ef299f3eda17c146 to your computer and use it in GitHub Desktop.
hooks.rb
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
require 'rubygems' | |
require 'pry' | |
class Hooks | |
def initialize; @callbacks ||= Hash.new({before: [], after: []}) end | |
def to_s; @callbacks.inspect; end | |
def register_hook(type, method_name, callback_method = nil, &block) | |
@callbacks[method_name][type].push(callback_method || block) | |
end | |
def invoke(scope_name, method_name, instance) | |
@callbacks[method_name][scope_name].each do |hook| | |
if hook.is_a?(Symbol) | |
instance.send(hook) | |
else | |
hook.yield(instance) | |
end | |
end | |
end | |
end | |
module Hookable | |
def self.included(base_klass) | |
unless Object.const_defined?("#{base_klass.name}Interceptor") | |
base_klass.extend(ClassMethods) | |
interceptor = const_set("#{base_klass.name}Interceptor", Module.new) | |
base_klass.send(:prepend, interceptor) | |
end | |
end | |
module ClassMethods | |
def hooks; @hooks ||= Hooks.new; end | |
def hook(type, method_name, callback_method = nil, &block) | |
interceptor = const_get("#{name}Interceptor") | |
hooks.register_hook(type, method_name, callback_method, &block) | |
interceptor.module_eval do | |
define_method(method_name) do |*args, &block| | |
self.class.hooks.invoke(:before, method_name, self) | |
super(*args, &block) | |
self.class.hooks.invoke(:after, method_name, self) | |
end | |
end | |
end | |
end | |
end | |
class Duck | |
include Hookable | |
attr_reader :name | |
def initialize; @name = 'Skrydzh'; end | |
hook :before, :make_sound do |object| | |
puts "In wild-wild forest..." | |
end | |
hook :after, :make_sound do |object| | |
puts "Bang-bang #{object.name}" | |
end | |
hook :after, :make_sound do |object| | |
puts "Kill-kill #{object.name}" | |
end | |
hook :after, :make_sound, :end_game | |
def make_sound; puts "Krya-krya, #{name}"; end | |
def end_game; puts "Game over"; end | |
end | |
duck = Duck.new | |
duck.make_sound |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment