Skip to content

Instantly share code, notes, and snippets.

@alisnic
Created November 28, 2012 17:05
Show Gist options
  • Save alisnic/4162558 to your computer and use it in GitHub Desktop.
Save alisnic/4162558 to your computer and use it in GitHub Desktop.
ruby method patterns
# Usage
# class Foo
# include MethodPatterns
#
# defp :greet, check(:nil?) do |obj|
# p 'HA! NIL!'
# end
#
# defp :greet, match_any do |obj|
# p 'Hey, Object!'
# end
# end
#
# foo = Foo.new
# foo.greet(nil) => 'HA! NIL!'
# foo.greet(1) => 'Hey, Object!'
module MethodPatterns
MethodPattern = Struct.new(:condition, :method)
PatternError = Class.new(StandardError)
module ClassMethods
def check (sym)
->(e) { sym.to_proc.call(e) }
end
def avoid (sym)
->(e) { !sym.to_proc.call(e) }
end
def match_any
->(e) { true }
end
def defp (method, cond, &block)
@method_patterns ||= {}
(@method_patterns[method] ||= []) << MethodPattern.new(cond, Proc.new(&block))
end
attr_reader :method_patterns
end
def execute_method_pattern (patterns, *args)
patterns.each do |mp|
return mp.method.call(*args) if mp.condition.call(*args)
end
raise MethodPatternError.new 'unmatched pattern'
end
def method_missing (method, *args, &block)
cache = self.class.method_patterns
if cache.has_key?(method)
execute_method_pattern(cache[method], *args)
else
super
end
end
def self.included (base)
base.extend(ClassMethods)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment