cuts 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 #=> "&lt;f&gt;"
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.
@@ -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
- def advices; @advices ||= {}; end
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
- methods = obj.methods + obj.private_methods - ['advices']
116
-
117
- methods.each do |sym|
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
- end
149
-
150
- end
151
-
152
- end
144
+ end #define_method
145
+ end #methods
146
+ end #def
153
147
 
154
148
  end
155
149
 
@@ -1,7 +1,8 @@
1
- require 'test/unit'
1
+ require 'microtest'
2
+ require 'ae'
2
3
  require 'cuts'
3
4
 
4
- class TestAop < Test::Unit::TestCase
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
- assert_equal(X, @x1.class)
28
+ @x1.class.assert == X
28
29
  end
29
30
 
30
31
  def test_public_methods
31
32
  meths = @x1.public_methods(false)
32
- assert(meths.include?("y"))
33
- assert(meths.include?("q"))
34
- assert(meths.include?("x"))
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
- assert_equal("{x}", @x1.x)
40
+ @x1.x.assert == "{x}"
39
41
  end
40
42
 
41
43
  def test_y
42
- assert_equal("y", @x1.y)
44
+ @x1.y.assert == "y"
43
45
  end
44
46
 
45
47
  def test_q
46
- assert_equal("<{x}>", @x1.q)
48
+ @x1.q.assert == "<{x}>"
47
49
  end
48
50
 
49
51
  end
@@ -1,7 +1,9 @@
1
- require 'test/unit'
1
+ require 'microtest'
2
+ require 'ae'
2
3
  require 'cuts'
3
4
 
4
- class TestCut < Test::Unit::TestCase
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
- o = X.new
16
- assert_equal("{x}", o.x)
17
+ o = X.new
18
+ o.x.assert == "{x}"
17
19
  end
18
20
 
19
21
  end
20
22
 
21
- class TestCut1 < Test::Unit::TestCase
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
- assert_equal( "<f>", f.f )
35
- assert_equal( F, f.class )
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
- assert_equal( "TestCut1::G", G.name )
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
- # assert_equal( [Q, G], F.cuts )
65
- # assert_equal( [Q, G], F.predecessors )
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
- assert_equal( F, f.class )
71
- assert_equal( "[<f>]", f.f )
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
- assert_equal( "TestCut2::G", G.name )
78
+ G.name.assert == "TestMultipleCuts::G"
77
79
  end
78
80
 
79
81
  def test_2_04
80
82
  assert(Q)
81
- assert_equal( "TestCut2::Q", Q.name )
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.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
- - tigerops-community@rubyforge.org
7
+ authors:
8
+ - Thomas Sawyer
9
+ - Peter Vanbroekhoven
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
-
12
- date: 2009-07-04 00:00:00 -04:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description: |-
17
- Cuts is an expiremental implementation of cut-based
18
- AOP for Ruby written in pure Ruby.
19
- email:
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
- extra_rdoc_files:
25
- - README
26
- - Rakefile
27
- - MANIFEST
28
- - RELEASE
29
- - LICENSE
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
- - meta/created
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
- - MANIFEST
52
- has_rdoc: true
53
- homepage: http://death.rubyforge.org
54
- licenses: []
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
- - --inline-source
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
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- version: "0"
70
- version:
71
- required_rubygems_version: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: "0"
76
- version:
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
- rubyforge_project: death
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: Cuts is an expiremental implementation of cut-based
84
- test_files:
85
- - test/test_cut.rb
86
- - test/test_aop.rb
95
+ summary: Cut-based AOP for Ruby
96
+ test_files: []