Class: Aspekt::Pointcut
Overview
Examples of usage can also be found in github.com/tione/aspekt/blob/development/spec/aspekt/pointcut_spec.rb
Instance Method Summary collapse
-
#has_matchers_for?(opts) ⇒ Boolean
Argument Hash with keys :class or :object and :method for checking if Pointcut is matching with a object or a class.
-
#initialize(*matchers) ⇒ Pointcut
constructor
Constructor takes for arguments Hash with keys class(es) or object(s) and method(s), or Array of Hash-es.
-
#matching ⇒ Object
Finds currently existing all Objects for this Pointcut.
Methods inherited from Object
Constructor Details
#initialize(*matchers) ⇒ Pointcut
Constructor takes for arguments Hash with keys class(es) or object(s) and method(s), or Array of Hash-es.
Example
Pointcut for object method
pointcut = Aspekt::Pointcut.new(type: :String, method: :to_s)
pointcut = Aspekt::Pointcut.new(type: /String/, method: /to_s/)
pointcut = Aspekt::Pointcut.new(type: String, method: 'to_s')
Pointcut for class method (singleton method)
pointcut = Aspekt::Pointcut.new(instance: String, method: :new)
pointcut = Aspekt::Pointcut.new(type: (class String; class<<self; self; end; end, method: :new)
pointcut = Aspekt::Pointcut.new(instance: some_object, method: /some_singleton_method/)
Pointcut with more than a one matcher
pointcut = Aspekt::Pointcut.new(
{type: String, method: :capitalize},
{types: [String, Array], methods: [/a/, /o/]},
{instances: [String, /Arr/], method: /new|try/}
)
Reasoning behind :type and :instance
-
using :type or :types (see: ruby-doc.org/core-1.9.3/BasicObject.html#method-i-instance_exec)
-
using :instance or :instances (see: ruby-doc.org/core-1.9.3/Module.html#method-i-module_exec)
41 42 43 44 45 |
# File 'lib/aspekt/pointcut.rb', line 41 def initialize *matchers raise ArgumentError, "must have matchers" if matchers.length == 0 matchers.each { |matcher| add_matcher matcher } end |
Instance Method Details
#has_matchers_for?(opts) ⇒ Boolean
Argument Hash with keys :class or :object and :method for checking if Pointcut is matching with a object or a class.
Example
pointcut = Aspekt::Pointcut.new(class: :SomeClass, method: :some_method).has_matchers_for?(class: SomeClass, method: :some_method)
pointcut = Aspekt::Pointcut.new(object: :SomeClass, method: :some_method).has_matchers_for?(object: SomeClass, method: :some_method)
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/aspekt/pointcut.rb', line 93 def has_matchers_for? opts raise ArgumentError, "has to include keys 'instance' or 'type', may include 'method'." unless opts[:instance] or opts[:type] # matcher_branch - from where to search matcher, thing - class or object matcher_branch, thing = case when opts[:instance]; [self[:instances], opts[:instance]]; when opts[:type]; [self[:types], opts[:type]]; end matchers_for_thing = matcher_branch.keys.including_same thing unless matchers_for_thing.length == 0 return true unless opts[:method] # we have no method matching and object is matching matcher_objects_methods = matcher_branch.values_at(*matchers_for_thing).flatten return true if matcher_objects_methods.include_same?(opts[:method]) # one of the matching object has matching method end return false # opts[:object] existed but no matcher was found end |
#matching ⇒ Object
Finds currently existing all Objects for this Pointcut. Returns Object and its method matchers.
Example
pointcut = Pointcut.new(types: [/Strin/, /^Hash$/, :ThisClassDoesNotExist)], instance: Array, methods: [/to/, :send])
pointcut_matching_types = pointcut.matching[:types] # will be: {String: [/to/, :send], Hash: [/to/, :send]}
pointcut_matching_instances = pointcut.matching[:instances] # will be: {Array: [/to/, :send]}
# if now ThisClassDoesNotExist will be defined and #matching is called again, then it will also contain it.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/aspekt/pointcut.rb', line 124 def matching matching = {} defined_classes = nil # this will be created for Regexp object matcher, if needed self.each do |type, object_matchers| matching[type] = {} object_matchers.each do |object_matcher, methods| case object_matcher when Symbol begin matching_class = object_matcher.to_s.split(/::/).inject(Object) {|a, b| a.const_get(b) } # throws NameError if does not exist matching[type][matching_class] = methods rescue NameError end when Regexp defined_classes ||= ObjectSpace.each_object(Class).to_a # do it when need it defined_classes.select {|defined_class| matching[type][defined_class] = methods if object_matcher.match(defined_class.name) } else matching[type][object_matcher] = methods end end end return matching end |