Module: MetaProgramming::Object::ClassMethods
- Defined in:
- lib/meta_programming/object.rb
Defined Under Namespace
Modules: Helpers
Instance Method Summary collapse
- #define_chained_method(method_name, ext, &block) ⇒ Object
- #define_ghost_method(matcher, &block) ⇒ Object
- #define_method_missing_chain(name, &block) ⇒ Object
- #method_access_level(method_name) ⇒ Object
- #safe_alias_method_chain(method_name, ext) ⇒ Object
Instance Method Details
#define_chained_method(method_name, ext, &block) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/meta_programming/object.rb', line 62 def define_chained_method(method_name, ext, &block) raise 'Must have a block defining the method body' unless block_given? with, without = Helpers.compose_chaining_symbols(method_name, ext) define_method(with, block) safe_alias_method_chain(method_name.to_sym, ext.to_sym) end |
#define_ghost_method(matcher, &block) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/meta_programming/object.rb', line 74 def define_ghost_method(matcher, &block) raise "Must have a block" unless block_given? raise ArgumentError, "Matcher argument must be either a 'string', :symbol, /regexp/ or proc" unless (matcher.nil? || [String, Symbol, Regexp, Proc].any?{|c| matcher.is_a?(c)}) uniq_ext = "#{self.name.gsub(/.+::/,'')}_#{matcher.class.name.gsub(/.+::/,'')}#{matcher.hash.abs.to_s}" _ghost_method_handler = "_ghost_method_handler_#{uniq_ext}".to_sym _ghost_method_matcher = "_ghost_method_matcher_#{uniq_ext}".to_sym define_method(_ghost_method_handler, block) private _ghost_method_handler if matcher.is_a?(Proc) define_method(_ghost_method_matcher, matcher) private _ghost_method_matcher end define_chained_method(:method_missing, uniq_ext.to_sym) do |symbol, *args| handled = case matcher when Regexp then !(symbol.to_s =~ matcher).nil? when String, Symbol then (symbol == matcher.to_sym) when Proc begin __send__(_ghost_method_matcher, symbol) rescue Exception => matcher_error raise matcher_error, "#{matcher_error.} in a ghost method matcher called for symbol :#{symbol}. Be sure to use self.class.method_defined? instead of respond_to? in a lambda matcher." end else nil end if handled begin __send__(_ghost_method_handler, (handled == true ? symbol : handled), *args) rescue Exception => handler_error raise handler_error, "#{handler_error.} in a ghost method block called with symbol :#{symbol}." end else __send__("method_missing_without_#{uniq_ext}".to_sym, symbol, *args) end end #cripple respond_to? in deference of 1.8 -- the include_private no longer works define_chained_method(:respond_to?, uniq_ext.to_sym) do |method_name| #1.9 only, include_private=nil| responds = case matcher when Regexp then !(method_name.to_s =~ matcher).nil? when String, Symbol then method_name == matcher.to_sym when Proc begin __send__(_ghost_method_matcher, method_name) rescue Exception => matcher_error raise matcher_error, "#{matcher_error.} in a ghost method matcher called in respond_to? for symbol :#{method_name}. Be sure to use self.class.method_defined? instead of respond_to? in a lambda matcher." end end responds || __send__("respond_to_without_#{uniq_ext}?".to_sym, method_name) #1.9 only, include_private) end end |
#define_method_missing_chain(name, &block) ⇒ Object
69 70 71 72 |
# File 'lib/meta_programming/object.rb', line 69 def define_method_missing_chain(name, &block) raise 'Must have block' unless block_given? define_chained_method(:method_missing, name.to_sym, &block) end |
#method_access_level(method_name) ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'lib/meta_programming/object.rb', line 29 def method_access_level(method_name) case when public_method_defined?(method_name.to_sym) then :public when private_method_defined?(method_name.to_sym) then :private when protected_method_defined?(method_name.to_sym) then :protected else nil end end |
#safe_alias_method_chain(method_name, ext) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/meta_programming/object.rb', line 38 def safe_alias_method_chain(method_name, ext) class_eval do method_name_with_ext, method_name_without_ext = Helpers.compose_chaining_symbols(method_name, ext) instance_variable = Helpers.escape_method_name(method_name_with_ext) if (method_defined?(method_name_with_ext) || private_method_defined?(method_name_with_ext)) raise(MetaProgramming::AliasMethodChainError, "#{method_name_without_ext} already exists. Circular references not permitted.") if (method_defined?(method_name_without_ext) || private_method_defined?(method_name_without_ext)) raise(MetaProgramming::AliasMethodChainError, "#{method_name_with_ext} already chained. Rechaining not permitted") if eigenclass.instance_variable_defined?("@#{instance_variable}") if (method_defined?(method_name.to_sym) || private_method_defined?(method_name.to_sym)) alias_method method_name_without_ext, method_name.to_sym alias_method method_name.to_sym, method_name_with_ext case method_access_level(method_name_without_ext) when :public then public(method_name.to_sym) when :protected then protected(method_name.to_sym) when :private then private(method_name.to_sym) end else define_method(method_name_without_ext) {|*args| } alias_method method_name.to_sym, method_name_with_ext end eigenclass.instance_variable_set("@#{instance_variable}", true) end end end |