aspekt 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +3 -0
- data/README.rdoc +19 -0
- data/lib/aspekt.rb +137 -0
- metadata +80 -0
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= IN THE MAKING, NOT USABLE
|
2
|
+
|
3
|
+
== Installation
|
4
|
+
|
5
|
+
Add to your Gemfile:
|
6
|
+
gem 'aspekt'
|
7
|
+
|
8
|
+
And run:
|
9
|
+
bundle install
|
10
|
+
|
11
|
+
Or run:
|
12
|
+
gem install aspekt
|
13
|
+
|
14
|
+
|
15
|
+
== Usage examples
|
16
|
+
|
17
|
+
=== Including before, after and around methods support into Object or Class
|
18
|
+
|
19
|
+
=== Creating aspects
|
data/lib/aspekt.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'is_same' # https://github.com/tione/is_same
|
2
|
+
|
3
|
+
|
4
|
+
# Supports only already existing objects (and classes) and methods Weaving.
|
5
|
+
# Aspects defined in folder ./aspects will add runtime loading.
|
6
|
+
#
|
7
|
+
# @see Aspekt::Pointcut
|
8
|
+
# @see Aspekt::Advice
|
9
|
+
module Aspekt
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
# All Aspekt's objects are extended from Aspekt::Object.
|
14
|
+
class Object < Hash
|
15
|
+
|
16
|
+
# Creates a new Aspekt::Object with base class Hash and registres self in class :@all.
|
17
|
+
def initialize opts
|
18
|
+
self.merge! opts
|
19
|
+
self.class.all << self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns all Objects created.
|
23
|
+
def self.all
|
24
|
+
@all ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class Pointcut < Aspekt::Object
|
31
|
+
|
32
|
+
# === Example usage
|
33
|
+
# class SomeClass
|
34
|
+
#
|
35
|
+
# def self.some_method
|
36
|
+
# return "some_value_from_singleton"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def some_method
|
40
|
+
# return "some_value"
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def other_method
|
44
|
+
# return "other_value"
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# some_object = SomeClass.new
|
50
|
+
#
|
51
|
+
# ==== Pointcuts for instance with types
|
52
|
+
# pointcut = Aspekt::Pointcut.new( class: :SomeClass, method: :some_method )
|
53
|
+
# pointcut = Aspekt::Pointcut.new( class: SomeClass, method: /some/ )
|
54
|
+
# pointcut = Aspekt::Pointcut.new( class: /Some/, method: /some/ )
|
55
|
+
#
|
56
|
+
# ==== Pointcut for class method (singleton method)
|
57
|
+
# pointcut = Aspekt::Pointcut.new( object: SomeClass, method: :some_method )
|
58
|
+
# pointcut = Aspekt::Pointcut.new( object: /Some/, method: /some/)
|
59
|
+
# pointcut = Aspekt::Pointcut.new( class: (class SomeClass; class<<self; self; end; end, method: :some_method )
|
60
|
+
#
|
61
|
+
# ==== Pointcut for only one object
|
62
|
+
# pointcut = Aspekt::Pointcut.new( object: some_object, method: :some_method)
|
63
|
+
#
|
64
|
+
# === Arguments
|
65
|
+
# - object: object, method: :method
|
66
|
+
# - [{object: object, method: :method}, {object: object2, method: :method2
|
67
|
+
# - objects: [object, object2], methods: [:method, :method2]
|
68
|
+
# - class: :SomeClass, methods: [:method, :method2]
|
69
|
+
# - [{objects: [Hash, Array], method: new}, {class: Array, method: :push}, {classes: [Hash, Array, SomeClass], method: /_id/}]
|
70
|
+
#
|
71
|
+
# ==== Limitations
|
72
|
+
# Instances of Regexp, Symbol and Constant are used as finders not thought of as objects.
|
73
|
+
# TODO: Fix. Possibly add a new hash key value?
|
74
|
+
|
75
|
+
def initialize *matchers
|
76
|
+
matchers = matchers.flatten.each do |matcher|
|
77
|
+
matcher[:classes] = [matcher.delete(:class)].flatten if matcher.has_key?(:class)
|
78
|
+
matcher[:objects] = [matcher.delete(:object)].flatten if matcher.has_key?(:object)
|
79
|
+
matcher[:methods] = [matcher.delete(:method)].flatten if matcher.has_key?(:method)
|
80
|
+
end
|
81
|
+
super matchers: matchers
|
82
|
+
end
|
83
|
+
|
84
|
+
# === Example usage
|
85
|
+
# pointcut = Aspekt::Pointcut.new( class: :SomeClass, method: :some_method ).is_matching?( object: SomeClass.new )
|
86
|
+
# pointcut = Aspekt::Pointcut.new( object: :SomeClass, method: :some_method ).is_matching?( object: SomeClass )
|
87
|
+
#
|
88
|
+
# === Arguments
|
89
|
+
# - object: object
|
90
|
+
# - object: object, method: :method
|
91
|
+
def is_matching? opts
|
92
|
+
raise ArgumentError, "has to include keys 'object', may include 'method'." unless opts[:object]
|
93
|
+
|
94
|
+
self[:matchers].each do |matcher|
|
95
|
+
# object matching
|
96
|
+
return true if
|
97
|
+
(matcher.has_key(:objects) and matcher[:objects].select{|object| object.is_same?(opts[:object])}.length > 0) or
|
98
|
+
(matcher.has_key(:classes) and matcher[:classes].select{|klass| klass.is_same?(opts[:object].class.name)}.length > 0)
|
99
|
+
# method matching
|
100
|
+
return true unless opts.has_key?(:methods) or
|
101
|
+
(matcher.has_key(:methods) and matcher[:methods].select{|klass| klass.is_same?(opts[:methods].class.name)}.length > 0)
|
102
|
+
end
|
103
|
+
|
104
|
+
return false
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
class Advice < Aspekt::Object
|
112
|
+
|
113
|
+
# == Example usage
|
114
|
+
# advice = Aspekt::Advice.new ( type: :before, pointcut: pointcut ) do |joinpoint|
|
115
|
+
# puts "before #{joinpoint}"
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# advice = Aspekt::Advice.new ( type: :around, pointcuts: [pointcut1, pointcut2]) do |joinpoint|
|
119
|
+
# puts "around :start for #{joinpoint}"
|
120
|
+
# return_value = joinpoint.proceed
|
121
|
+
# puts "around :end for #{joinpoint}"
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
def initialize opts
|
125
|
+
opts[:pointcuts] = [opts.delete(:pointcut)].flatten if opts[:pointcut]
|
126
|
+
super opts
|
127
|
+
raise ArgumentError, "type has to be Symbol: before, after or around" unless [:before, :after, :around].include?(self[:type])
|
128
|
+
raise ArgumentError, "no pointcut defined" unless self[:pointcuts].length
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aspekt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Margus Pärt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-13 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: is_same
|
16
|
+
requirement: &22453880 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *22453880
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &22453420 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *22453420
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdoc
|
38
|
+
requirement: &22453000 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *22453000
|
47
|
+
description: Before, after and around method calls. Supports Regexp matching.
|
48
|
+
email: margus@tione.eu
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- README.rdoc
|
54
|
+
- Gemfile
|
55
|
+
- lib/aspekt.rb
|
56
|
+
homepage: https://github.com/tione/aspekt
|
57
|
+
licenses: []
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.9.2
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.8.15
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: IN THE MAKING, NOT USABLE.
|
80
|
+
test_files: []
|