Created
July 13, 2012 02:32
-
-
Save rinaldifonseca/3102335 to your computer and use it in GitHub Desktop.
Ruby SuperSimpleCallbacks
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 'observer' | |
module SuperSimpleCallbacks | |
include Observable | |
def self.included(klass) | |
klass.extend ClassMethods | |
klass.initialize_included_features | |
end | |
# the observed is made also observer | |
def initialize | |
add_observer(self) | |
end | |
# TODO: dry | |
def update(method_name, callback_type) # hook for the observer | |
case callback_type | |
when :before then self.class.callbacks[:before][method_name.to_sym].each{|callback| send callback} | |
when :after then self.class.callbacks[:after][method_name.to_sym].each{|callback| send callback} | |
end | |
end | |
module ClassMethods | |
def initialize_included_features | |
@callbacks = Hash.new | |
@callbacks[:before] = Hash.new{|h,k| h[k] = []} | |
@callbacks[:after] = @callbacks[:before].clone | |
class << self | |
attr_accessor :callbacks | |
end | |
end | |
def method_added(method) | |
redefine_method(method) if is_a_callback?(method) | |
end | |
def is_a_callback?(method) | |
registered_methods.include?(method) | |
end | |
def registered_methods | |
callbacks.values.map(&:keys).flatten.uniq | |
end | |
def store_callbacks(type, method_name, *callback_methods) | |
callbacks[type.to_sym][method_name.to_sym] += callback_methods.flatten.map(&:to_sym) | |
end | |
def before(original_method, *callbacks) | |
store_callbacks(:before, original_method, *callbacks) | |
end | |
def after(original_method, *callbacks) | |
store_callbacks(:after, original_method, *callbacks) | |
end | |
def objectify_and_remove_method(method) | |
if method_defined?(method.to_sym) | |
original = instance_method(method.to_sym) | |
remove_method(method.to_sym) | |
original | |
else | |
nil | |
end | |
end | |
def redefine_method(original_method) | |
original = objectify_and_remove_method(original_method) | |
mod = Module.new | |
mod.class_eval do | |
define_method(original_method.to_sym) do | |
changed; notify_observers(original_method, :before) | |
original.bind(self).call if original | |
changed; notify_observers(original_method, :after) | |
end | |
end | |
include mod | |
end | |
end | |
end | |
class MyObservedHouse | |
include SuperSimpleCallbacks | |
before :party, [:walk_dinosaure, :prepare, :just_idle] | |
after :party, [:just_idle, :keep_house, :walk_dinosaure] | |
before :home_office, [:just_idle, :prepare, :just_idle] | |
after :home_office, [:just_idle, :walk_dinosaure, :just_idle] | |
before :second_level, [:party] | |
def home_office | |
puts "learning and working with ruby...".upcase | |
end | |
def party | |
puts "having party...".upcase | |
end | |
def just_idle | |
puts "...." | |
end | |
def prepare | |
puts "preparing snacks..." | |
end | |
def keep_house | |
puts "house keeping..." | |
end | |
def walk_dinosaure | |
puts "walking the dinosaure..." | |
end | |
def second_level | |
puts "second level..." | |
end | |
end | |
MyObservedHouse.new.tap do |house| | |
puts "-------------------------" | |
puts "-- about calling party --" | |
puts "-------------------------" | |
house.party | |
puts "-------------------------------" | |
puts "-- about calling home_office --" | |
puts "-------------------------------" | |
house.home_office | |
puts "--------------------------------" | |
puts "-- about calling second_level --" | |
puts "--------------------------------" | |
house.second_level | |
end | |
# => ... | |
# ------------------------- | |
# -- about calling party -- | |
# ------------------------- | |
# walking the dinosaure... | |
# preparing snacks... | |
# .... | |
# HAVING PARTY... | |
# .... | |
# house keeping... | |
# walking the dinosaure... | |
# ------------------------------- | |
# -- about calling home_office -- | |
# ------------------------------- | |
# .... | |
# preparing snacks... | |
# .... | |
# LEARNING AND WORKING WITH RUBY... | |
# .... | |
# walking the dinosaure... | |
# .... | |
# -------------------------------- | |
# -- about calling second_level -- | |
# -------------------------------- | |
# walking the dinosaure... | |
# preparing snacks... | |
# .... | |
# HAVING PARTY... | |
# .... | |
# house keeping... | |
# walking the dinosaure... | |
# second level... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment