Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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
Add Comment
Please, Sign In to add comment