cuts 1.0.0 → 1.1.0
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/.ruby +52 -0
- data/{RELEASE → HISTORY.rdoc} +35 -2
- data/NOTICE.rdoc +33 -0
- data/RCR.textile +457 -0
- data/README.rdoc +82 -0
- data/lib/cuts/aop.rb +26 -32
- data/test/test_aop.rb +11 -9
- data/test/test_cut.rb +18 -16
- metadata +81 -71
- data/HISTORY +0 -18
- data/LICENSE +0 -168
- data/MANIFEST +0 -23
- data/README +0 -47
- data/Rakefile +0 -10
- data/meta/abstract +0 -3
- data/meta/contact +0 -1
- data/meta/created +0 -1
- data/meta/homepage +0 -1
- data/meta/license +0 -1
- data/meta/package +0 -1
- data/meta/project +0 -1
- data/meta/summary +0 -1
- data/meta/version +0 -1
data/README.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
= Cuts - Cut-based AOP for Ruby
|
2
|
+
|
3
|
+
{Homepage}[http://rubyworks.github.com/cuts] |
|
4
|
+
{Source Code}[http://github.com/rubyworks/cuts] |
|
5
|
+
{Issue Tracker}[http://github.com/rubyworks/cuts/issues]
|
6
|
+
|
7
|
+
{<img src="http://travis-ci.org/rubyworks/cuts.png" />}[http://travis-ci.org/rubyworks/cuts]
|
8
|
+
|
9
|
+
|
10
|
+
== Description
|
11
|
+
|
12
|
+
Cuts is an expiremental pure-Ruby implimentation of cut-base AOP.
|
13
|
+
Cuts are a failry low-level system, so implementing them in pure-Ruby is no
|
14
|
+
simple accomplishment, even for a language as reflective and metaprogrammable
|
15
|
+
as Ruby.
|
16
|
+
|
17
|
+
|
18
|
+
== History
|
19
|
+
|
20
|
+
Cuts started it's life as a discussion about AOP on Ruby-talk, which led to
|
21
|
+
a in-depth discussion between Trans and Peter Vanbroekhoven. The outcome of those talks
|
22
|
+
were three projects. {Suby}[http://suby.rubyforge.org] an early expiremental
|
23
|
+
branch of Ruby; the RCRFoundry, a section of the Ruby Garden Wiki dedicated to jointly
|
24
|
+
developing RCRs; and the {Cut-based AOP RCR}[rcr.html]. The RCR of course,
|
25
|
+
ultimately led to this project, as well as an expiremental Ruby 1.8.3 core
|
26
|
+
implementation (see the Suby homepage). We continue to touch up the {RCR}[rcr.html]
|
27
|
+
but on the whole it is now complete.
|
28
|
+
|
29
|
+
Please read {Cut-based AOP for Ruby RCR}[rcr.html].
|
30
|
+
|
31
|
+
This Cuts library comes by way of {Ruby Facets}[http://rubyworks.github.com/facets],
|
32
|
+
where the implementation was orginally housed. Becuase of it's expiremental nature,
|
33
|
+
it was deemd best to move it into it's own project as part of the ongoing work to
|
34
|
+
make Facets a rock solid library. Despite being expiremental, this implementation
|
35
|
+
does pass it's unit test. However, it has had litte trial in integrated tests.
|
36
|
+
It will be interesting to see if this library, as it matures, can prove robust
|
37
|
+
enough for production use. In either case, clearly it would be preferable to have
|
38
|
+
a Ruby-core implementation instead, but that potential is completely in other
|
39
|
+
persons hands.
|
40
|
+
|
41
|
+
|
42
|
+
== Usage
|
43
|
+
|
44
|
+
Here is a quick and dirty example:
|
45
|
+
|
46
|
+
require 'cuts'
|
47
|
+
|
48
|
+
class C
|
49
|
+
def f ; "f" ; end
|
50
|
+
end
|
51
|
+
|
52
|
+
cut :G < C do
|
53
|
+
def f; '<'+super+'>' ; end
|
54
|
+
end
|
55
|
+
|
56
|
+
c = C.new
|
57
|
+
|
58
|
+
c.f #=> "<f>"
|
59
|
+
|
60
|
+
|
61
|
+
For detailed usage documentation, please refer to the {API Documentation}[http://rubydoc.info/gems/cuts].
|
62
|
+
|
63
|
+
|
64
|
+
== Install
|
65
|
+
|
66
|
+
Install via RubyGems:
|
67
|
+
|
68
|
+
$ gem install cuts
|
69
|
+
|
70
|
+
|
71
|
+
== Special Thanks
|
72
|
+
|
73
|
+
Special thanks to Peter Van Broekhoven. The man is a genius!
|
74
|
+
|
75
|
+
|
76
|
+
== Legal
|
77
|
+
|
78
|
+
(FreeBSD License)
|
79
|
+
|
80
|
+
Cuts, Copyright (c) 2007 Thomas Sawyer & Peter Van Broekhoven
|
81
|
+
|
82
|
+
See NOTICE.rdoc for details.
|
data/lib/cuts/aop.rb
CHANGED
@@ -1,22 +1,11 @@
|
|
1
|
-
# TITLE:
|
2
|
-
#
|
3
|
-
# Aspect Oriented Programming for Ruby
|
4
|
-
#
|
5
|
-
# SUMMARY:
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# AUTHORS:
|
9
|
-
#
|
10
|
-
# - Thomas Sawyer
|
11
|
-
#
|
12
|
-
# NOTES:
|
13
|
-
#
|
14
|
-
# - Can JointPoint and Target be the same class?
|
15
|
-
|
16
1
|
require 'cuts/cut'
|
17
2
|
|
18
|
-
|
3
|
+
require 'pp'
|
19
4
|
|
5
|
+
# TODO: Can JointPoint and Target be the same class?
|
6
|
+
|
7
|
+
# Aspect Oriented Programming for Ruby using Cuts.
|
8
|
+
#
|
20
9
|
class Aspect < Module
|
21
10
|
|
22
11
|
def initialize(&block)
|
@@ -104,23 +93,31 @@ end
|
|
104
93
|
|
105
94
|
|
106
95
|
def cross_cut(klass)
|
96
|
+
|
107
97
|
Cut.new(klass) do
|
108
|
-
define_method :__base__ do klass end
|
109
98
|
|
110
|
-
|
99
|
+
define_method :__base__ do
|
100
|
+
klass
|
101
|
+
end
|
102
|
+
|
103
|
+
def advices
|
104
|
+
@advices ||= {}
|
105
|
+
end
|
111
106
|
|
112
107
|
def self.extended(obj)
|
113
108
|
base = obj.class #__base__
|
114
109
|
|
115
|
-
|
116
|
-
|
117
|
-
|
110
|
+
# use string for 1.9-, and symbol for 1.9+
|
111
|
+
methods = obj.methods +
|
112
|
+
obj.public_methods +
|
113
|
+
obj.protected_methods +
|
114
|
+
obj.private_methods -
|
115
|
+
[:advices, 'advices']
|
118
116
|
|
117
|
+
methods.uniq.each do |sym|
|
119
118
|
#meth = obj.method(sym)
|
120
|
-
|
121
|
-
define_method(sym) do |*args| #, &blk| # TODO imporove interface mirroring
|
119
|
+
define_method(sym) do |*args, &blk|
|
122
120
|
jp = Joinpoint.new(self, base, sym, *args) #, &blk)
|
123
|
-
|
124
121
|
# calculate advices on first use.
|
125
122
|
unless advices[sym]
|
126
123
|
advices[sym] = []
|
@@ -136,20 +133,17 @@ def cross_cut(klass)
|
|
136
133
|
end
|
137
134
|
|
138
135
|
if advices[sym].empty?
|
139
|
-
super
|
136
|
+
super(*args, &blk)
|
140
137
|
else
|
141
138
|
target = jp #Target.new(self, sym, *args, &blk) # Target == JoinPoint ?
|
142
139
|
advices[sym].each do |(aspect, advice)|
|
143
140
|
target = Target.new(aspect, advice, target)
|
144
141
|
end
|
145
|
-
target.super
|
142
|
+
target.call #super
|
146
143
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
144
|
+
end #define_method
|
145
|
+
end #methods
|
146
|
+
end #def
|
153
147
|
|
154
148
|
end
|
155
149
|
|
data/test/test_aop.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'microtest'
|
2
|
+
require 'ae'
|
2
3
|
require 'cuts'
|
3
4
|
|
4
|
-
class
|
5
|
+
class AOPTest < MicroTest::TestCase
|
5
6
|
|
6
7
|
class X
|
7
8
|
def x; "x"; end
|
@@ -24,26 +25,27 @@ class TestAop < Test::Unit::TestCase
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def test_class
|
27
|
-
|
28
|
+
@x1.class.assert == X
|
28
29
|
end
|
29
30
|
|
30
31
|
def test_public_methods
|
31
32
|
meths = @x1.public_methods(false)
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
meths = meths.map{ |m| m.to_s }
|
34
|
+
meths.assert.include?("y")
|
35
|
+
meths.assert.include?("q")
|
36
|
+
meths.assert.include?("x")
|
35
37
|
end
|
36
38
|
|
37
39
|
def test_x
|
38
|
-
|
40
|
+
@x1.x.assert == "{x}"
|
39
41
|
end
|
40
42
|
|
41
43
|
def test_y
|
42
|
-
|
44
|
+
@x1.y.assert == "y"
|
43
45
|
end
|
44
46
|
|
45
47
|
def test_q
|
46
|
-
|
48
|
+
@x1.q.assert == "<{x}>"
|
47
49
|
end
|
48
50
|
|
49
51
|
end
|
data/test/test_cut.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'microtest'
|
2
|
+
require 'ae'
|
2
3
|
require 'cuts'
|
3
4
|
|
4
|
-
|
5
|
+
#
|
6
|
+
class TestCutNew < MicroTest::TestCase
|
5
7
|
|
6
8
|
class X
|
7
9
|
def x; "x"; end
|
@@ -12,13 +14,14 @@ class TestCut < Test::Unit::TestCase
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def test_method_is_wrapped_by_advice
|
15
|
-
|
16
|
-
|
17
|
+
o = X.new
|
18
|
+
o.x.assert == "{x}"
|
17
19
|
end
|
18
20
|
|
19
21
|
end
|
20
22
|
|
21
|
-
|
23
|
+
#
|
24
|
+
class TestLiteralSyntax < MicroTest::TestCase
|
22
25
|
|
23
26
|
class F
|
24
27
|
def f ; "f" ; end
|
@@ -31,20 +34,19 @@ class TestCut1 < Test::Unit::TestCase
|
|
31
34
|
|
32
35
|
def test_1_01
|
33
36
|
f = F.new
|
34
|
-
|
35
|
-
|
37
|
+
f.f.assert == "<f>"
|
38
|
+
f.class.assert == F
|
36
39
|
end
|
37
40
|
|
38
41
|
def test_1_02
|
39
42
|
assert(G)
|
40
|
-
|
43
|
+
G.name.assert == "TestLiteralSyntax::G"
|
41
44
|
end
|
42
45
|
|
43
46
|
end
|
44
47
|
|
45
48
|
# Test multiple cuts.
|
46
|
-
|
47
|
-
class TestCut2 < Test::Unit::TestCase
|
49
|
+
class TestMultipleCuts < MicroTest::TestCase
|
48
50
|
|
49
51
|
class F
|
50
52
|
def f ; "f" ; end
|
@@ -61,24 +63,24 @@ class TestCut2 < Test::Unit::TestCase
|
|
61
63
|
end
|
62
64
|
|
63
65
|
#def test_2_01
|
64
|
-
#
|
65
|
-
#
|
66
|
+
# F.cuts.assert == [Q, G]
|
67
|
+
# F.predecessors.assert == [Q, G]
|
66
68
|
#end
|
67
69
|
|
68
70
|
def test_2_02
|
69
71
|
f = F.new
|
70
|
-
|
71
|
-
|
72
|
+
f.class.assert == F
|
73
|
+
f.f.assert == "[<f>]"
|
72
74
|
end
|
73
75
|
|
74
76
|
def test_2_03
|
75
77
|
assert(G)
|
76
|
-
|
78
|
+
G.name.assert == "TestMultipleCuts::G"
|
77
79
|
end
|
78
80
|
|
79
81
|
def test_2_04
|
80
82
|
assert(Q)
|
81
|
-
|
83
|
+
Q.name.assert == "TestMultipleCuts::Q"
|
82
84
|
end
|
83
85
|
|
84
86
|
end
|
metadata
CHANGED
@@ -1,86 +1,96 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuts
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
-
-
|
7
|
+
authors:
|
8
|
+
- Thomas Sawyer
|
9
|
+
- Peter Vanbroekhoven
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
date: 2011-10-27 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: detroit
|
17
|
+
requirement: &18946520 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *18946520
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: microtest
|
28
|
+
requirement: &18945920 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *18945920
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: ae
|
39
|
+
requirement: &18945380 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *18945380
|
48
|
+
description: Cuts is an expiremental implementation of cut-based AOP for Ruby written
|
49
|
+
in pure Ruby.
|
50
|
+
email:
|
51
|
+
- transfire@gmail.com
|
20
52
|
executables: []
|
21
|
-
|
22
53
|
extensions: []
|
23
|
-
|
24
|
-
|
25
|
-
- README
|
26
|
-
-
|
27
|
-
-
|
28
|
-
|
29
|
-
-
|
30
|
-
- HISTORY
|
31
|
-
files:
|
32
|
-
- Rakefile
|
33
|
-
- RELEASE
|
34
|
-
- LICENSE
|
35
|
-
- README
|
36
|
-
- HISTORY
|
37
|
-
- lib/cuts.rb
|
54
|
+
extra_rdoc_files:
|
55
|
+
- HISTORY.rdoc
|
56
|
+
- README.rdoc
|
57
|
+
- NOTICE.rdoc
|
58
|
+
- RCR.textile
|
59
|
+
files:
|
60
|
+
- .ruby
|
38
61
|
- lib/cuts/aop.rb
|
39
62
|
- lib/cuts/cut.rb
|
40
|
-
-
|
41
|
-
- meta/homepage
|
42
|
-
- meta/summary
|
43
|
-
- meta/abstract
|
44
|
-
- meta/package
|
45
|
-
- meta/version
|
46
|
-
- meta/license
|
47
|
-
- meta/project
|
48
|
-
- meta/contact
|
49
|
-
- test/test_cut.rb
|
63
|
+
- lib/cuts.rb
|
50
64
|
- test/test_aop.rb
|
51
|
-
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
- test/test_cut.rb
|
66
|
+
- HISTORY.rdoc
|
67
|
+
- README.rdoc
|
68
|
+
- NOTICE.rdoc
|
69
|
+
- RCR.textile
|
70
|
+
homepage: http://rubyworks.github.com/cuts
|
71
|
+
licenses:
|
72
|
+
- BSD-2-Clause
|
73
|
+
- BSD-2-Clause
|
56
74
|
post_install_message:
|
57
|
-
rdoc_options:
|
58
|
-
|
59
|
-
- --title
|
60
|
-
- cuts api
|
61
|
-
- --main
|
62
|
-
- README
|
63
|
-
require_paths:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
64
77
|
- lib
|
65
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
77
90
|
requirements: []
|
78
|
-
|
79
|
-
|
80
|
-
rubygems_version: 1.3.4
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.8.10
|
81
93
|
signing_key:
|
82
94
|
specification_version: 3
|
83
|
-
summary:
|
84
|
-
test_files:
|
85
|
-
- test/test_cut.rb
|
86
|
-
- test/test_aop.rb
|
95
|
+
summary: Cut-based AOP for Ruby
|
96
|
+
test_files: []
|