Skip to content

Instantly share code, notes, and snippets.

@jhbabon
Created May 11, 2012 15:08
Show Gist options
  • Save jhbabon/2660340 to your computer and use it in GitHub Desktop.
Save jhbabon/2660340 to your computer and use it in GitHub Desktop.
Callbacks module for Ruby classes
# encoding: utf-8
# Small module to add the ability to register callbacks at class level to use it at instace level.
# With this module you can create small DSLs on your classes.
#
# Example usage:
#
# class Person
# include ::Callbacks
#
# def self.setup(&block)
# _register_callback(:setup, block)
# end
#
# def hello(a)
# _execute_callback(:setup, a)
# end
# end
#
# Person.setup { |a| puts "Hello #{a}!!" }
# p = Person.new
# p.hello('world')
# # => "Hello world!!"
#
module Callbacks
def self.included(base)
base.class_eval do
class << self
def _callbacks
@_callbacks ||= Hash.new { |h, k| h[k] = [Proc.new { |*| }, []] }
end
protected :_callbacks
def _register_callback(name, block, *arguments)
_callbacks[name] = [block, arguments]
end
protected :_register_callback
end
def _execute_callback(name, *arguments)
block, extra = _registered_callbacks[name]
arguments = arguments + extra
instance_exec *arguments, &block
end
protected :_execute_callback
def _registered_callbacks
@_registered_callbacks ||= self.class.send(:_callbacks).dup
end
protected :_registered_callbacks
# Modify a callback at instance level, without mess with the
# callbacks registered in the class
def _modify_callback(name, block, *arguments)
_registered_callbacks[name] = [block, arguments]
end
protected :_modify_callback
end
end
end
# encoding: utf-8
class Person
include ::Callbacks
def self.setup(&block)
_register_callback(:setup, block)
end
def hello(a)
_execute_callback(:setup, a)
end
end
Person.setup { |a| puts "Hello #{a}!!" }
# encoding: utf-8
require './callbacks'
require './person'
someone = Person.new
$stdout.puts someone.hello "there" # => Hello there!!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment