Skip to content

Instantly share code, notes, and snippets.

@MaherSaif
Forked from RyanScottLewis/rulebook_rewrite.rb
Created December 22, 2010 01:19
Show Gist options
  • Save MaherSaif/750926 to your computer and use it in GitHub Desktop.
Save MaherSaif/750926 to your computer and use it in GitHub Desktop.
module RuleBook
def RuleBook.add_rules(object, instance_or_class, rules)
instance_or_class = instance_or_class.to_s.downcase.strip.to_sym
raise(ArgumentError, "'instance_or_class' must equal :instance or :class") unless [:instance, :class].include?(instance_or_class)
raise(ArgumentError, "'rules' must be a Hash") unless rules.is_a?(Hash)
unless object.instance_variable_get(:@_rulebook_initiated) # Class instance variable. Not class variable. Not instance variable. Is confusing.
object.instance_variable_set(:@_rulebook_initiated, true)
object.instance_variable_set(:@_rulebook, {:instance=>{}, :class=>{}}) # @_rulebook is actually two rulebooks, instance and class
end
case instance_or_class
when :instance then object.instance_eval { include RuleBook::InstanceMethods }
when :class then object.instance_eval { extend RuleBook::ClassMethods }
end
object.instance_variable_get(:@_rulebook)[instance_or_class].merge!(rules)
end
def RuleBook.find_and_call_rule_if_exists(object, instance_or_class, method, *args, &blk)
instance_or_class = instance_or_class.to_s.downcase.strip.to_sym
raise(ArgumentError, "'instance_or_class' must equal :instance or :class") unless [:instance, :class].include?(instance_or_class)
where_to_find_rulebook = instance_or_class == :instance ? object.class : object
rulebook = where_to_find_rulebook.instance_variable_get(:@_rulebook)[instance_or_class]
matching_rules = rulebook.find_all{ |a| regex = a.first; !!regex.match(method.to_s) }
unless matching_rules.empty?
last_result = nil
matching_rules.each do |regex, method_assigned_to_rule|
match = regex.match(method)
last_result = object.send(method_assigned_to_rule, *match.captures, *args)
end
last_result
else
raise(NoMethodError, "method '#{method}' does not exist.")
end
end
module InstanceMethods
def method_missing(method, *args, &blk)
RuleBook.find_and_call_rule_if_exists(self, :instance, method, *args, &blk)
end
end
module ClassMethods
def method_missing(method, *args, &blk)
RuleBook.find_and_call_rule_if_exists(self, :class, method, *args, &blk)
end
end
end
class Module
def instance_rule(rules)
RuleBook.add_rules(self, :instance, rules)
end
def class_rule(rules)
RuleBook.add_rules(self, :class, rules)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment