teejayvanslyke-gazer 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/History.txt +4 -0
- data/Manifest.txt +13 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +79 -0
- data/VERSION.yml +4 -0
- data/lib/gazer.rb +12 -0
- data/lib/gazer/aspect.rb +9 -0
- data/lib/gazer/aspect/base.rb +38 -0
- data/lib/gazer/aspect/filter.rb +38 -0
- data/lib/gazer/aspect/instance_of.rb +21 -0
- data/lib/gazer/aspect/join_point.rb +8 -0
- data/lib/gazer/aspect/pointcut.rb +34 -0
- data/lib/gazer/object_extensions.rb +141 -0
- data/lib/gazer/rails.rb +4 -0
- data/lib/gazer/rails/action_controller.rb +19 -0
- data/spec/gazer_spec.rb +181 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/test/test_aspect_generator.rb +46 -0
- data/test/test_generator_helper.rb +29 -0
- metadata +76 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
= gazer
|
2
|
+
|
3
|
+
* http://github.com/teejayvanslyke/gazer
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Poor man's aspect-oriented programming for Ruby.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Elegant DSL
|
12
|
+
* before & after pointcuts.
|
13
|
+
* Rails integration.
|
14
|
+
|
15
|
+
== ROADMAP:
|
16
|
+
|
17
|
+
* Locking down Object monkeypatching scheme.
|
18
|
+
* More selectors and pointcuts.
|
19
|
+
* Regular-expression-based pointcuts.
|
20
|
+
* <tt>:only</tt> and <tt>except</tt> options for Rails helper.
|
21
|
+
|
22
|
+
== SYNOPSIS:
|
23
|
+
|
24
|
+
Gazer's DSL is accessible to subclasses of Gazer::Aspect::Base.
|
25
|
+
|
26
|
+
class LoggingAspect < Gazer::Aspect::Base
|
27
|
+
|
28
|
+
before instances_of(Article) => :create do |point|
|
29
|
+
puts "Creating article"
|
30
|
+
end
|
31
|
+
|
32
|
+
after instances_of([Article, Comment]) => :save do |point|
|
33
|
+
puts "Saved #{point.object}."
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
I have also provided a Rails generator for generating aspects for
|
39
|
+
your project. Simply execute the following:
|
40
|
+
|
41
|
+
$ script/generate aspect logging
|
42
|
+
|
43
|
+
A template will be created at <tt>app/aspects/logging_aspect.rb</tt>
|
44
|
+
for your aspect-oriented pleasure.
|
45
|
+
|
46
|
+
To include an aspect for a given controller, use the aspect class method:
|
47
|
+
|
48
|
+
class MyController < ApplicationController
|
49
|
+
aspect :logging
|
50
|
+
end
|
51
|
+
|
52
|
+
== INSTALL:
|
53
|
+
|
54
|
+
$ sudo gem install teejayvanslyke-gazer
|
55
|
+
|
56
|
+
== LICENSE:
|
57
|
+
|
58
|
+
(The MIT License)
|
59
|
+
|
60
|
+
Copyright (c) 2009 T.J. VanSlyke
|
61
|
+
|
62
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
63
|
+
a copy of this software and associated documentation files (the
|
64
|
+
'Software'), to deal in the Software without restriction, including
|
65
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
66
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
67
|
+
permit persons to whom the Software is furnished to do so, subject to
|
68
|
+
the following conditions:
|
69
|
+
|
70
|
+
The above copyright notice and this permission notice shall be
|
71
|
+
included in all copies or substantial portions of the Software.
|
72
|
+
|
73
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
74
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
75
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
76
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
77
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
78
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
79
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION.yml
ADDED
data/lib/gazer.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
|
5
|
+
module Gazer
|
6
|
+
VERSION = '0.0.1'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'gazer/object_extensions'
|
10
|
+
require 'gazer/aspect'
|
11
|
+
require 'gazer/rails' if defined?(RAILS_ENV)
|
12
|
+
|
data/lib/gazer/aspect.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'aspect/join_point'
|
5
|
+
require 'aspect/pointcut'
|
6
|
+
require 'aspect/base'
|
7
|
+
require 'aspect/filter'
|
8
|
+
require 'aspect/instance_of'
|
9
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module Gazer
|
3
|
+
module Aspect
|
4
|
+
class Base
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def add_pointcut(pointcut)
|
9
|
+
@pointcuts ||= []
|
10
|
+
@pointcuts << pointcut
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :pointcuts
|
14
|
+
|
15
|
+
def instances_of(klass)
|
16
|
+
InstancesOf.new(klass)
|
17
|
+
end
|
18
|
+
|
19
|
+
def apply!
|
20
|
+
pointcuts.each do |pc| pc.apply! end
|
21
|
+
end
|
22
|
+
|
23
|
+
def before(selector, &block)
|
24
|
+
add_pointcut BeforePointcut.new(selector, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def after(selector, &block)
|
28
|
+
add_pointcut AfterPointcut.new(selector, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def around(selector, &block)
|
32
|
+
add_pointcut AroundPointcut.new(selector, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gazer
|
2
|
+
module Aspect
|
3
|
+
class Filter
|
4
|
+
def initialize(expr)
|
5
|
+
if expr.is_a?(Array)
|
6
|
+
@types = expr
|
7
|
+
else
|
8
|
+
@types = [ expr ]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def advise_before(sym, &block)
|
13
|
+
@types.each {|t| t.advise_before(sym, &block)}
|
14
|
+
end
|
15
|
+
|
16
|
+
def advise_around(sym, &block)
|
17
|
+
@types.each {|t| t.advise_around(sym, &block)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def advise_after(sym, &block)
|
21
|
+
@types.each {|t| t.advise_after(sym, &block)}
|
22
|
+
end
|
23
|
+
|
24
|
+
def advise_instances_before(sym, &block)
|
25
|
+
@types.each {|t| t.advise_instances_before(sym, &block)}
|
26
|
+
end
|
27
|
+
|
28
|
+
def advise_instances_around(sym, &block)
|
29
|
+
@types.each {|t| t.advise_instances_around(sym, &block)}
|
30
|
+
end
|
31
|
+
|
32
|
+
def advise_instances_after(sym, &block)
|
33
|
+
@types.each {|t| t.advise_instances_after(sym, &block)}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gazer
|
2
|
+
module Aspect
|
3
|
+
class InstancesOf
|
4
|
+
def initialize(filter)
|
5
|
+
@filter = Filter.new(filter)
|
6
|
+
end
|
7
|
+
|
8
|
+
def advise_before(sym, &block)
|
9
|
+
@filter.advise_instances_before(sym, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def advise_around(sym, &block)
|
13
|
+
@filter.advise_instances_around(sym, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def advise_after(sym, &block)
|
17
|
+
@filter.advise_instances_after(sym, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Gazer
|
2
|
+
module Aspect
|
3
|
+
class Pointcut
|
4
|
+
def initialize(selector, &block)
|
5
|
+
@selector = selector
|
6
|
+
@block = block
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class BeforePointcut < Pointcut
|
11
|
+
def apply!
|
12
|
+
@selector.keys.each do |key|
|
13
|
+
Filter.new(key).advise_before(@selector[key], &@block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class AfterPointcut < Pointcut
|
19
|
+
def apply!
|
20
|
+
@selector.keys.each do |key|
|
21
|
+
Filter.new(key).advise_after(@selector[key], &@block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class AroundPointcut < Pointcut
|
27
|
+
def apply!
|
28
|
+
@selector.keys.each do |key|
|
29
|
+
Filter.new(key).advise_around(@selector[key], &@block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Gazer
|
2
|
+
|
3
|
+
module ObjectExtensions
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def advise(sym, block)
|
7
|
+
@advice ||= {}
|
8
|
+
@advice[sym] ||= []
|
9
|
+
@advice[sym] << block
|
10
|
+
end
|
11
|
+
|
12
|
+
def advice
|
13
|
+
@advice ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def advice_for(sym)
|
17
|
+
@advice[sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def backup_method(sym)
|
21
|
+
id = "__#{sym}_#{backup_methods_for(sym).size}__"
|
22
|
+
alias_method id, sym # Backup original method
|
23
|
+
private id # Make backup private
|
24
|
+
@backup_methods_for ||= {}
|
25
|
+
@backup_methods_for[sym] ||= []
|
26
|
+
@backup_methods_for[sym] << id
|
27
|
+
return id
|
28
|
+
end
|
29
|
+
|
30
|
+
def backup_methods_for(sym)
|
31
|
+
@backup_methods_for ||= {}
|
32
|
+
@backup_methods_for[sym] ||= []
|
33
|
+
end
|
34
|
+
|
35
|
+
def unadvise_all
|
36
|
+
advice.each do |sym, arr|
|
37
|
+
code = <<-CODE
|
38
|
+
class << self
|
39
|
+
alias_method #{sym.inspect}, '__#{sym}_0__'
|
40
|
+
public #{sym.inspect}
|
41
|
+
end
|
42
|
+
CODE
|
43
|
+
instance_eval(code)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def advise_before(sym, &block)
|
48
|
+
return unless respond_to?(sym)
|
49
|
+
advise(sym, block)
|
50
|
+
code = <<-CODE
|
51
|
+
class << self
|
52
|
+
hook = backup_method(#{sym.inspect})
|
53
|
+
define_method #{sym.inspect} do |*args|
|
54
|
+
self.advice_for(#{sym.inspect}).last.call(
|
55
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
56
|
+
:method => #{sym.inspect},
|
57
|
+
:args => args))
|
58
|
+
__send__ hook, *args # Invoke backup
|
59
|
+
end
|
60
|
+
end
|
61
|
+
CODE
|
62
|
+
instance_eval(code)
|
63
|
+
end
|
64
|
+
|
65
|
+
def advise_around(sym, &block)
|
66
|
+
return unless respond_to?(sym)
|
67
|
+
advise(sym, block)
|
68
|
+
code = <<-CODE
|
69
|
+
class << self
|
70
|
+
hook = backup_method(#{sym.inspect})
|
71
|
+
define_method #{sym.inspect} do |*args|
|
72
|
+
self.advice_for(#{sym.inspect}).last.call(
|
73
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
74
|
+
:method => #{sym.inspect},
|
75
|
+
:args => args))
|
76
|
+
__send__ hook, *args # Invoke backup
|
77
|
+
end
|
78
|
+
end
|
79
|
+
CODE
|
80
|
+
instance_eval(code)
|
81
|
+
end
|
82
|
+
|
83
|
+
def advise_after(sym, &block)
|
84
|
+
return unless respond_to?(sym)
|
85
|
+
advise(sym, block)
|
86
|
+
code = <<-CODE
|
87
|
+
class << self
|
88
|
+
hook = backup_method(#{sym.inspect})
|
89
|
+
define_method #{sym.inspect} do |*args|
|
90
|
+
rval = __send__ hook, *args # Invoke backup
|
91
|
+
self.advice_for(#{sym.inspect}).last.call(
|
92
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
93
|
+
:method => #{sym.inspect},
|
94
|
+
:args => args))
|
95
|
+
return rval
|
96
|
+
end
|
97
|
+
end
|
98
|
+
CODE
|
99
|
+
instance_eval(code)
|
100
|
+
end
|
101
|
+
|
102
|
+
def advise_instances_before(sym, &block)
|
103
|
+
hook = backup_method(sym)
|
104
|
+
define_method sym do |*args|
|
105
|
+
block.call(
|
106
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
107
|
+
:method => sym,
|
108
|
+
:args => args))
|
109
|
+
__send__ hook, *args # Invoke backup
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def advise_instances_around(sym, &block)
|
114
|
+
hook = backup_method(sym)
|
115
|
+
define_method sym do |*args|
|
116
|
+
block.call(
|
117
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
118
|
+
:method => sym,
|
119
|
+
:args => args))
|
120
|
+
__send__ hook, *args
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def advise_instances_after(sym, &block)
|
125
|
+
hook = backup_method(sym)
|
126
|
+
define_method sym do |*args| # Replace method
|
127
|
+
rval = __send__ hook, *args # Invoke backup
|
128
|
+
block.call(
|
129
|
+
Gazer::Aspect::JoinPoint.new(:object => self,
|
130
|
+
:method => sym,
|
131
|
+
:args => args))
|
132
|
+
return rval
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
Object.extend(Gazer::ObjectExtensions::ClassMethods)
|
data/lib/gazer/rails.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gazer
|
2
|
+
module Rails
|
3
|
+
module ActionController
|
4
|
+
module ClassMethods
|
5
|
+
def aspect(*args)
|
6
|
+
args.each do |aspect|
|
7
|
+
define_method "__apply_#{aspect}_aspect__" do
|
8
|
+
eval("#{aspect.to_s.classify}Aspect.apply!")
|
9
|
+
end
|
10
|
+
|
11
|
+
before_filter "__apply_#{aspect}_aspect__"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
ActionController::Base.extend(Gazer::Rails::ActionController::ClassMethods)
|
data/spec/gazer_spec.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
|
4
|
+
def message(text) end
|
5
|
+
describe Gazer do
|
6
|
+
|
7
|
+
include Gazer
|
8
|
+
|
9
|
+
class Dog
|
10
|
+
|
11
|
+
def self.create
|
12
|
+
new
|
13
|
+
end
|
14
|
+
|
15
|
+
def bark!
|
16
|
+
"woof!"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class Cat
|
22
|
+
def hiss!
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_away!
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.get_scared
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "advising instance methods" do
|
33
|
+
|
34
|
+
describe "before the method call" do
|
35
|
+
|
36
|
+
it "executes the advice provided before the method is executed" do
|
37
|
+
|
38
|
+
@cat = Cat.new
|
39
|
+
|
40
|
+
Dog.advise_instances_before(:bark!) do |point|
|
41
|
+
@cat.hiss!
|
42
|
+
end
|
43
|
+
|
44
|
+
@dog = Dog.new
|
45
|
+
@cat.should_receive(:hiss!)
|
46
|
+
@dog.bark!
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "after the method call" do
|
53
|
+
|
54
|
+
it "executes the advice provided after the method is executed" do
|
55
|
+
|
56
|
+
@cat = Cat.new
|
57
|
+
|
58
|
+
Dog.advise_instances_after(:bark!) do |point|
|
59
|
+
@cat.run_away!
|
60
|
+
end
|
61
|
+
|
62
|
+
@dog = Dog.new
|
63
|
+
@cat.should_receive(:run_away!)
|
64
|
+
@dog.bark!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "advising class methods" do
|
72
|
+
|
73
|
+
describe "before the method call" do
|
74
|
+
|
75
|
+
it "executes the advice provided before the method is executed" do
|
76
|
+
|
77
|
+
Dog.unadvise_all
|
78
|
+
Cat.unadvise_all
|
79
|
+
|
80
|
+
Dog.advise_before(:create) do |point|
|
81
|
+
Cat.get_scared
|
82
|
+
end
|
83
|
+
|
84
|
+
Cat.should_receive(:get_scared)
|
85
|
+
@dog = Dog.create
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "after the method call" do
|
92
|
+
|
93
|
+
it "executes the advice provided after the method is executed" do
|
94
|
+
|
95
|
+
Dog.unadvise_all
|
96
|
+
|
97
|
+
Dog.advise_after(:create) do |point|
|
98
|
+
Cat.get_scared
|
99
|
+
end
|
100
|
+
|
101
|
+
Cat.should_receive(:get_scared)
|
102
|
+
@dog = Dog.create
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "after instantiating an instance already" do
|
109
|
+
|
110
|
+
before :each do
|
111
|
+
Dog.unadvise_all
|
112
|
+
Cat.unadvise_all
|
113
|
+
|
114
|
+
@dog = Dog.new
|
115
|
+
@cat = Cat.new
|
116
|
+
end
|
117
|
+
|
118
|
+
it "does not execute the advice if none has been defined" do
|
119
|
+
@cat.should_not_receive(:hiss!)
|
120
|
+
@dog.bark!
|
121
|
+
end
|
122
|
+
|
123
|
+
it "executes the advice provided on the already-instantiated instance" do
|
124
|
+
Dog.advise_instances_after(:bark!) do |point|
|
125
|
+
@cat.hiss!
|
126
|
+
end
|
127
|
+
|
128
|
+
@cat.should_receive(:hiss!)
|
129
|
+
@dog.bark!
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "aspect DSL" do
|
137
|
+
class TestAspect < Gazer::Aspect::Base
|
138
|
+
before instances_of(Dog) => :bark! do |point|
|
139
|
+
Cat.get_scared
|
140
|
+
end
|
141
|
+
|
142
|
+
after instances_of(Cat) => :hiss! do |point|
|
143
|
+
Dog.new
|
144
|
+
end
|
145
|
+
|
146
|
+
before Dog => :create do |point|
|
147
|
+
message("creating #{point.object.name}")
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.message(text)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
before :all do
|
155
|
+
TestAspect.apply!
|
156
|
+
end
|
157
|
+
|
158
|
+
before :each do
|
159
|
+
@dog = Dog.new
|
160
|
+
@cat = Cat.new
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
it "makes the cat run away before the dog barks" do
|
165
|
+
Cat.should_receive(:get_scared)
|
166
|
+
@dog.bark!
|
167
|
+
end
|
168
|
+
|
169
|
+
it "creates a new dog after the cat hisses" do
|
170
|
+
Dog.should_receive(:new)
|
171
|
+
@cat.hiss!
|
172
|
+
end
|
173
|
+
|
174
|
+
it "messages that we are creating a new Dog" do
|
175
|
+
TestAspect.should_receive(:message).with("creating Dog")
|
176
|
+
Dog.create
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
|
2
|
+
|
3
|
+
require 'rails_generator'
|
4
|
+
|
5
|
+
class TestAspectGenerator < Test::Unit::TestCase
|
6
|
+
include RubiGen::GeneratorTestHelper
|
7
|
+
|
8
|
+
def setup
|
9
|
+
bare_setup
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
bare_teardown
|
14
|
+
end
|
15
|
+
|
16
|
+
# Some generator-related assertions:
|
17
|
+
# assert_generated_file(name, &block) # block passed the file contents
|
18
|
+
# assert_directory_exists(name)
|
19
|
+
# assert_generated_class(name, &block)
|
20
|
+
# assert_generated_module(name, &block)
|
21
|
+
# assert_generated_test_for(name, &block)
|
22
|
+
# The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file
|
23
|
+
# assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet)
|
24
|
+
#
|
25
|
+
# Other helper methods are:
|
26
|
+
# app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files)
|
27
|
+
# bare_setup - place this in setup method to create the APP_ROOT folder for each test
|
28
|
+
# bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
|
29
|
+
|
30
|
+
def test_generator_without_options
|
31
|
+
name = "myapp"
|
32
|
+
run_generator('aspect', [name], sources)
|
33
|
+
assert_directory_exists "some/directory"
|
34
|
+
assert_generated_file "some_file"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def sources
|
39
|
+
[RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path))
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
def generator_path
|
44
|
+
"rails_generators"
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
begin
|
2
|
+
require File.dirname(__FILE__) + '/test_helper'
|
3
|
+
rescue LoadError
|
4
|
+
require 'test/unit'
|
5
|
+
end
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
# Must set before requiring generator libs.
|
9
|
+
TMP_ROOT = File.dirname(__FILE__) + "/tmp" unless defined?(TMP_ROOT)
|
10
|
+
PROJECT_NAME = "myproject" unless defined?(PROJECT_NAME)
|
11
|
+
app_root = File.join(TMP_ROOT, PROJECT_NAME)
|
12
|
+
if defined?(APP_ROOT)
|
13
|
+
APP_ROOT.replace(app_root)
|
14
|
+
else
|
15
|
+
APP_ROOT = app_root
|
16
|
+
end
|
17
|
+
if defined?(RAILS_ROOT)
|
18
|
+
RAILS_ROOT.replace(app_root)
|
19
|
+
else
|
20
|
+
RAILS_ROOT = app_root
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'rubigen'
|
25
|
+
rescue LoadError
|
26
|
+
require 'rubygems'
|
27
|
+
require 'rubigen'
|
28
|
+
end
|
29
|
+
require 'rubigen/helpers/generator_test_helper'
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: teejayvanslyke-gazer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- T.J. VanSlyke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-17 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: poor man's aspect-oriented programming for Ruby
|
17
|
+
email: T.J. VanSlyke
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- History.txt
|
26
|
+
- Manifest.txt
|
27
|
+
- PostInstall.txt
|
28
|
+
- README.rdoc
|
29
|
+
- VERSION.yml
|
30
|
+
- lib/gazer
|
31
|
+
- lib/gazer/aspect
|
32
|
+
- lib/gazer/aspect/base.rb
|
33
|
+
- lib/gazer/aspect/filter.rb
|
34
|
+
- lib/gazer/aspect/instance_of.rb
|
35
|
+
- lib/gazer/aspect/join_point.rb
|
36
|
+
- lib/gazer/aspect/pointcut.rb
|
37
|
+
- lib/gazer/aspect.rb
|
38
|
+
- lib/gazer/object_extensions.rb
|
39
|
+
- lib/gazer/rails
|
40
|
+
- lib/gazer/rails/action_controller.rb
|
41
|
+
- lib/gazer/rails.rb
|
42
|
+
- lib/gazer.rb
|
43
|
+
- test/test_aspect_generator.rb
|
44
|
+
- test/test_generator_helper.rb
|
45
|
+
- spec/gazer_spec.rb
|
46
|
+
- spec/spec.opts
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/teejayvanslyke/gazer
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --inline-source
|
53
|
+
- --charset=UTF-8
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.2.0
|
72
|
+
signing_key:
|
73
|
+
specification_version: 2
|
74
|
+
summary: poor man's aspect-oriented programming for Ruby
|
75
|
+
test_files: []
|
76
|
+
|