glue 0.29.0 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ProjectInfo +17 -29
- data/README +2 -2
- data/doc/RELEASES +8 -0
- data/lib/glue.rb +5 -5
- data/lib/glue/autoreload.rb +2 -2
- data/lib/glue/builder.rb +17 -6
- data/lib/glue/builder/xml.rb +4 -13
- data/lib/glue/cache/drb.rb +2 -3
- data/lib/glue/cache/file.rb +3 -3
- data/lib/glue/configuration.rb +124 -40
- data/lib/glue/fixture.rb +2 -1
- data/lib/glue/localization.rb +2 -1
- data/lib/glue/property.rb +13 -9
- data/test/glue/tc_aspects.rb +4 -6
- data/test/glue/tc_configuration.rb +12 -3
- data/test/glue/tc_fixture.rb +56 -2
- data/test/glue/tc_flexob.rb +2 -1
- data/test/glue/tc_stores.rb +2 -1
- metadata +43 -57
- data/Rakefile +0 -222
- data/lib/glue/aspects.rb +0 -230
- data/lib/glue/expirable.rb +0 -39
- data/lib/glue/on_included.rb +0 -48
- data/lib/glue/paramix.rb +0 -233
data/lib/glue/aspects.rb
DELETED
@@ -1,230 +0,0 @@
|
|
1
|
-
require 'facet/inheritor'
|
2
|
-
|
3
|
-
module Glue
|
4
|
-
|
5
|
-
# An Aspect is a class that defines advices.
|
6
|
-
|
7
|
-
class Aspect
|
8
|
-
class << self
|
9
|
-
def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
|
10
|
-
target.send(:include, Glue::Aspects) unless target.ancestors.include?(Glue::Aspects)
|
11
|
-
target.wrap(self, :pre => pre, :post => post)
|
12
|
-
end
|
13
|
-
|
14
|
-
alias_method :observe, :wrap
|
15
|
-
end
|
16
|
-
|
17
|
-
def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
|
18
|
-
target.send(:include, Glue::Aspects) unless target.ancestors.include?(Glue::Aspects)
|
19
|
-
target.wrap(self, :pre => pre, :post => post)
|
20
|
-
end
|
21
|
-
alias_method :observe, :wrap
|
22
|
-
end
|
23
|
-
|
24
|
-
# Add support for Aspect Oriented Programming (AOP).
|
25
|
-
#
|
26
|
-
# === Examples
|
27
|
-
#
|
28
|
-
# class Controller
|
29
|
-
# pre :force_login, :where => :prepend
|
30
|
-
# wrap Benchmark, :on => :index
|
31
|
-
# post :taraa, :on => login
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# module Timestamped
|
35
|
-
# pre :on => :og_insert { |this| this.create_time = Time.now }
|
36
|
-
# pre :on => :og_update { |this| this.update_time = Time.now }
|
37
|
-
# pre :on => [:og_insert, :og_update] { |this| this.create_time = Time.now }
|
38
|
-
# end
|
39
|
-
|
40
|
-
module Aspects
|
41
|
-
|
42
|
-
# Store the code and the metadata (options) for
|
43
|
-
# an Advice.
|
44
|
-
|
45
|
-
Advice = Struct.new(:code, :options)
|
46
|
-
|
47
|
-
# Apply the advices to the target class.
|
48
|
-
|
49
|
-
def self.wrap(target, methods = target.instance_methods)
|
50
|
-
include_advice_modules(target)
|
51
|
-
|
52
|
-
for m in [methods].flatten
|
53
|
-
args = []
|
54
|
-
target.instance_method(m).arity.times { |i| args << "a#{i}" }
|
55
|
-
args = args.join(',')
|
56
|
-
|
57
|
-
target.module_eval <<-end_eval, __FILE__, __LINE__
|
58
|
-
alias_method :__unwrapped_#{m}, :#{m}
|
59
|
-
def #{m}(#{args})
|
60
|
-
#{gen_advice_code(m, target.advices, :pre)}
|
61
|
-
__unwrapped_#{m}(#{args})
|
62
|
-
#{gen_advice_code(m, target.advices, :post)}
|
63
|
-
end
|
64
|
-
end_eval
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
class << self
|
69
|
-
alias_method :apply_advices, :wrap
|
70
|
-
end
|
71
|
-
|
72
|
-
# Include Modules that define advices.
|
73
|
-
|
74
|
-
def self.include_advice_modules(target)
|
75
|
-
add_advices = []
|
76
|
-
del_advices = []
|
77
|
-
|
78
|
-
for a in target.advices
|
79
|
-
if a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
|
80
|
-
target.module_eval %{ include #{a.code} }
|
81
|
-
|
82
|
-
options = a.options.reject { |k,v| k == :pre || k == :post }
|
83
|
-
|
84
|
-
method = (a.options[:pre] || 'pre').to_s
|
85
|
-
if a.code.instance_methods.include?(method)
|
86
|
-
options.update(:where => :prepend, :join => :pre)
|
87
|
-
add_advices << Advice.new(method.to_sym, options)
|
88
|
-
end
|
89
|
-
|
90
|
-
method = (a.options[:post] || 'post').to_s
|
91
|
-
if a.code.instance_methods.include?(method)
|
92
|
-
options.update(:where => :append, :join => :post)
|
93
|
-
add_advices << Advice.new(method.to_sym, options)
|
94
|
-
end
|
95
|
-
|
96
|
-
del_advices << a
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Delete the original advices.
|
101
|
-
|
102
|
-
for a in del_advices
|
103
|
-
target.advices!.delete(a)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Add the new advices.
|
107
|
-
|
108
|
-
target.advices!.concat(add_advices)
|
109
|
-
end
|
110
|
-
|
111
|
-
# Generates the code to call the aspects.
|
112
|
-
|
113
|
-
def self.gen_advice_code(method, advices, join = :pre) # :nodoc:
|
114
|
-
code = ''
|
115
|
-
|
116
|
-
advices.each_with_index do |advice, idx|
|
117
|
-
o = options = advice.options
|
118
|
-
|
119
|
-
if only = options[:only] || options[:on]
|
120
|
-
next unless [only].flatten.include?(method.to_sym)
|
121
|
-
elsif except = options[:except]
|
122
|
-
next if [except].flatten.include?(method.to_sym)
|
123
|
-
end
|
124
|
-
|
125
|
-
advice = advice.code
|
126
|
-
|
127
|
-
if advice.is_a?(Symbol) or advice.is_a?(String)
|
128
|
-
next if o[:join] != join
|
129
|
-
code << "#{advice}; "
|
130
|
-
elsif advice.respond_to?('call')
|
131
|
-
next if o[:join] != join
|
132
|
-
code << "self.class.advices[#{idx}].code.call(self); "
|
133
|
-
elsif advice.is_a?(Class)
|
134
|
-
if advice.class.ancestors.include?(Class)
|
135
|
-
if m = o[join] and advice.methods.include?(m.to_s)
|
136
|
-
code << "#{advice}.#{m}(self); "
|
137
|
-
end
|
138
|
-
else
|
139
|
-
# Module, allready handled.
|
140
|
-
end
|
141
|
-
else
|
142
|
-
if m = o[join] and advice.methods.include?(m.to_s)
|
143
|
-
code << "self.class.advices[#{idx}].code.#{m}(self); "
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
return code
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.append_features(base)
|
152
|
-
super
|
153
|
-
base.extend(ClassMethods)
|
154
|
-
base.inheritor :advices, [], :+
|
155
|
-
end
|
156
|
-
|
157
|
-
module ClassMethods
|
158
|
-
|
159
|
-
# Add a pre (before) advice.
|
160
|
-
|
161
|
-
def pre(*args, &block)
|
162
|
-
o = options = {
|
163
|
-
:join => :pre,
|
164
|
-
:where => :prepend,
|
165
|
-
}
|
166
|
-
options.update(args.pop) if args.last.is_a?(Hash)
|
167
|
-
|
168
|
-
if block_given?
|
169
|
-
new_advices = [ Advice.new(block, options) ]
|
170
|
-
else
|
171
|
-
new_advices = args.collect { |a| Advice.new(a, options) }
|
172
|
-
end
|
173
|
-
=begin
|
174
|
-
if options[:where] == :prepend
|
175
|
-
self.advices = advices + self.advices
|
176
|
-
else
|
177
|
-
self.advices = self.advices + advices
|
178
|
-
end
|
179
|
-
=end
|
180
|
-
self.advices!.concat(new_advices)
|
181
|
-
end
|
182
|
-
alias_method :before, :pre
|
183
|
-
|
184
|
-
# Add a post (after) advice.
|
185
|
-
|
186
|
-
def post(*args, &block)
|
187
|
-
o = options = {
|
188
|
-
:join => :post,
|
189
|
-
:where => :append,
|
190
|
-
}
|
191
|
-
options.update(args.pop) if args.last.is_a?(Hash)
|
192
|
-
|
193
|
-
if block_given?
|
194
|
-
new_advices = [ Advice.new(block, options) ]
|
195
|
-
else
|
196
|
-
new_advices = args.collect { |a| Advice.new(a, options) }
|
197
|
-
end
|
198
|
-
=begin
|
199
|
-
if options[:where] == :prepend
|
200
|
-
self.advices = advices + self.advices
|
201
|
-
else
|
202
|
-
self.advices = self.advices + advices
|
203
|
-
end
|
204
|
-
=end
|
205
|
-
self.advices!.concat(new_advices)
|
206
|
-
end
|
207
|
-
alias_method :after, :post
|
208
|
-
|
209
|
-
# Add a wrap (arround) aspect. An aspect is a class that
|
210
|
-
# responds to the before and after advices.
|
211
|
-
|
212
|
-
def wrap(*args)
|
213
|
-
o = options = {
|
214
|
-
:pre => :pre,
|
215
|
-
:post => :post
|
216
|
-
}
|
217
|
-
options.update(args.pop) if args.last.is_a?(Hash)
|
218
|
-
|
219
|
-
for aspect in args
|
220
|
-
self.advices! << Advice.new(aspect, options)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
alias_method :around, :wrap
|
224
|
-
alias_method :observer, :wrap
|
225
|
-
|
226
|
-
end
|
227
|
-
|
228
|
-
end
|
229
|
-
|
230
|
-
end
|
data/lib/glue/expirable.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Glue
|
2
|
-
|
3
|
-
# Generic expiring functionality mixin.
|
4
|
-
|
5
|
-
module Expirable
|
6
|
-
attr_accessor :expires
|
7
|
-
|
8
|
-
# Set the expires timeout for this entry.
|
9
|
-
|
10
|
-
def expires_after(timeout = (60*60*24))
|
11
|
-
@expires = Time.now + timeout
|
12
|
-
end
|
13
|
-
|
14
|
-
# Set the expire timeout for this entry. The timeout happens
|
15
|
-
# after (base + rand(spread)) seconds.
|
16
|
-
|
17
|
-
def expires_spread(base, spread)
|
18
|
-
@expires = Time.now + base + rand(spread)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Is this entry expired?
|
22
|
-
|
23
|
-
def expired?
|
24
|
-
if @expires.nil? or (Time.now > @expires)
|
25
|
-
return true
|
26
|
-
else
|
27
|
-
return false
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Update the expiration period. Override in your application.
|
32
|
-
|
33
|
-
def touch!
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
# * George Moschovitis <gm@navel.gr>
|
data/lib/glue/on_included.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# George Moschovitis <gm@navel.gr>
|
2
|
-
|
3
|
-
class Module
|
4
|
-
|
5
|
-
# A useful macro for dynamic modules.
|
6
|
-
#--
|
7
|
-
# FIXME: quick and easy implementation, should
|
8
|
-
# come up with something better. The name
|
9
|
-
# sucks too.
|
10
|
-
#++
|
11
|
-
def on_included(code)
|
12
|
-
tag = caller[0].split(' ').first.split(/\/|\\/).last.gsub(/:|\.|\(|\)/, '_')
|
13
|
-
old = "__included_#{tag}"
|
14
|
-
module_eval %{
|
15
|
-
class << self
|
16
|
-
alias_method :#{old}, :included
|
17
|
-
def included(base)
|
18
|
-
#{old}(base)
|
19
|
-
#{code}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
}
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
=begin Testing
|
27
|
-
|
28
|
-
module M
|
29
|
-
on_included %{
|
30
|
-
puts 'hello'
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
module Q
|
35
|
-
on_included %{
|
36
|
-
puts 'world'
|
37
|
-
}
|
38
|
-
on_included %{
|
39
|
-
puts 'it works'
|
40
|
-
}
|
41
|
-
end
|
42
|
-
|
43
|
-
class C
|
44
|
-
include M
|
45
|
-
include Q
|
46
|
-
end
|
47
|
-
|
48
|
-
=end
|
data/lib/glue/paramix.rb
DELETED
@@ -1,233 +0,0 @@
|
|
1
|
-
# gmosx: replaces gems/facet_more-1.0.1/lib/facet/paramix.rb
|
2
|
-
# to make Nitro work, till we come up with a better solution.
|
3
|
-
#
|
4
|
-
# This is a temporary solution until the Facets version is
|
5
|
-
# fixed.
|
6
|
-
|
7
|
-
#--
|
8
|
-
# Parametric Mixins
|
9
|
-
#
|
10
|
-
# Copyright (c) 2005 Thomas Sawyer and George Moschovitis
|
11
|
-
#
|
12
|
-
# Ruby License
|
13
|
-
#
|
14
|
-
# This module is free software. You may use, modify, and/or redistribute this
|
15
|
-
# software under the same terms as Ruby.
|
16
|
-
#
|
17
|
-
# This program is distributed in the hope that it will be useful, but WITHOUT
|
18
|
-
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
19
|
-
# FOR A PARTICULAR PURPOSE.
|
20
|
-
#
|
21
|
-
# ==========================================================================
|
22
|
-
# Revision History
|
23
|
-
# --------------------------------------------------------------------------
|
24
|
-
# 2005-12-02 trans * Simplified into fine elegance.
|
25
|
-
# 2005-09-19 trans * Cleaned up and renamed.
|
26
|
-
# 2005-04-28 trans * Added to Calibre.
|
27
|
-
# ==========================================================================
|
28
|
-
#
|
29
|
-
#++
|
30
|
-
|
31
|
-
require 'facet/module/basename'
|
32
|
-
|
33
|
-
#:title: Parametric Mixins
|
34
|
-
#
|
35
|
-
# Parametric Mixins provides parameters for mixin modules.
|
36
|
-
# Module parameters can be set at the time of inclusion or extension,
|
37
|
-
# then accessed via an instance method of the same name as the included
|
38
|
-
# module.
|
39
|
-
#
|
40
|
-
# == Synopsis
|
41
|
-
#
|
42
|
-
# module Mixin
|
43
|
-
# def hello
|
44
|
-
# puts "Hello from #{Mixin(:name)}"
|
45
|
-
# end
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# class MyClass
|
49
|
-
# include Mixin, :name => 'Ruby'
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# m = MyClass.new
|
53
|
-
# m.hello -> 'Hello from Ruby'
|
54
|
-
#
|
55
|
-
# You can view the full set of parameters via the #mixin_parameters
|
56
|
-
# class method, which returns a hash keyed on the included modules.
|
57
|
-
#
|
58
|
-
# MyClass.mixin_parameters #=> {Mixin=>{:name=>'Ruby'}}
|
59
|
-
# MyClass.mixin_parameters[Mixin] #=> {:name=>'Ruby'}
|
60
|
-
#
|
61
|
-
# To create _dynamic mixins_ you can use the #included callback
|
62
|
-
# method along with mixin_parameters method like so:
|
63
|
-
#
|
64
|
-
# module Mixin
|
65
|
-
# def included( base )
|
66
|
-
# parms = base.mixin_parameters[self]
|
67
|
-
# base.class_eval {
|
68
|
-
# def hello
|
69
|
-
# puts "Hello from #{parms(:name)}"
|
70
|
-
# end
|
71
|
-
# }
|
72
|
-
# end
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
# More conveniently a new callback has been added, #included_with_parameters,
|
76
|
-
# which passes in the parameters in addition to the base class/module.
|
77
|
-
#
|
78
|
-
# module Mixin
|
79
|
-
# def included_with_parameters( base, parms )
|
80
|
-
# base.class_eval {
|
81
|
-
# def hello
|
82
|
-
# puts "Hello from #{parms(:name)}"
|
83
|
-
# end
|
84
|
-
# }
|
85
|
-
# end
|
86
|
-
# end
|
87
|
-
#
|
88
|
-
# We would prefer to have passed the parameters through the #included callback
|
89
|
-
# method itself, but implementation of such a feature is much more complicated.
|
90
|
-
# If a reasonable solution presents itself in the future however, we will fix.
|
91
|
-
#
|
92
|
-
# == Author(s)
|
93
|
-
#
|
94
|
-
# * George Moschovitis
|
95
|
-
# * Thomas Sawyer
|
96
|
-
#
|
97
|
-
|
98
|
-
class Module
|
99
|
-
|
100
|
-
# Store for module parameters. This is local per module
|
101
|
-
# and indexed on module/class included-into.
|
102
|
-
def mixin_parameters ; @mixin_parameters ||= {} ; end
|
103
|
-
|
104
|
-
alias_method :include_without_parameters, :include
|
105
|
-
|
106
|
-
def include(*args)
|
107
|
-
params = args.last.is_a?(Hash) ? args.pop : {}
|
108
|
-
=begin
|
109
|
-
for mod in args
|
110
|
-
mixin_parameters[mod] = params
|
111
|
-
define_method( mod.basename ) do |key|
|
112
|
-
if params.key?(key)
|
113
|
-
params[key]
|
114
|
-
else
|
115
|
-
super if defined?( super )
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
=end
|
120
|
-
r = include_without_parameters(*args)
|
121
|
-
for mod in args
|
122
|
-
mod.included_with_parameters( self, params ) if mod.respond_to?(:included_with_parameters)
|
123
|
-
end
|
124
|
-
r
|
125
|
-
end
|
126
|
-
|
127
|
-
alias_method :extend_without_parameters, :extend
|
128
|
-
|
129
|
-
def extend(*args)
|
130
|
-
params = args.last.is_a?(Hash) ? args.pop : nil
|
131
|
-
=begin
|
132
|
-
for mod in args
|
133
|
-
(class << self; self; end).class_eval do
|
134
|
-
mixin_parameters[mod] = params
|
135
|
-
define_method( mod.basename ) do |key|
|
136
|
-
if params.key?(key)
|
137
|
-
params[key]
|
138
|
-
else
|
139
|
-
super if defined?( super )
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
=end
|
145
|
-
r = extend_without_parameters(*args)
|
146
|
-
extended_with_parameters( self, params ) if method_defined?(:extended_with_parameters)
|
147
|
-
r
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
# _____ _
|
155
|
-
# |_ _|__ ___| |_
|
156
|
-
# | |/ _ \/ __| __|
|
157
|
-
# | | __/\__ \ |_
|
158
|
-
# |_|\___||___/\__|
|
159
|
-
#
|
160
|
-
|
161
|
-
=begin test
|
162
|
-
|
163
|
-
require 'test/unit'
|
164
|
-
require 'facet/kernel/adhoc'
|
165
|
-
|
166
|
-
class TC01 < Test::Unit::TestCase
|
167
|
-
|
168
|
-
module M
|
169
|
-
def f
|
170
|
-
M(:p)
|
171
|
-
end
|
172
|
-
def self.included_with_parameters( base, parms )
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
class C
|
177
|
-
include M, :p => "check"
|
178
|
-
end
|
179
|
-
|
180
|
-
class D
|
181
|
-
include M, :p => "steak"
|
182
|
-
end
|
183
|
-
|
184
|
-
def test_01_001
|
185
|
-
c = C.new
|
186
|
-
assert_equal( "check", c.f )
|
187
|
-
end
|
188
|
-
|
189
|
-
def test_01_002
|
190
|
-
d = D.new
|
191
|
-
assert_equal( "steak", d.f )
|
192
|
-
end
|
193
|
-
|
194
|
-
def test_01_003
|
195
|
-
assert_equal( {M=>{:p => "check"}}, C.mixin_parameters )
|
196
|
-
assert_equal( {M=>{:p => "steak"}}, D.mixin_parameters )
|
197
|
-
end
|
198
|
-
|
199
|
-
end
|
200
|
-
|
201
|
-
|
202
|
-
class TC02 < Test::Unit::TestCase
|
203
|
-
|
204
|
-
module M
|
205
|
-
def f
|
206
|
-
M(:p)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
class C
|
211
|
-
extend M, :p => "mosh"
|
212
|
-
end
|
213
|
-
|
214
|
-
class D
|
215
|
-
extend M, :p => "many"
|
216
|
-
end
|
217
|
-
|
218
|
-
def test_02_001
|
219
|
-
assert_equal( "mosh", C.f )
|
220
|
-
end
|
221
|
-
|
222
|
-
def test_02_002
|
223
|
-
assert_equal( "many", D.f )
|
224
|
-
end
|
225
|
-
|
226
|
-
def test_02_003
|
227
|
-
assert_equal( {M=>{:p => "mosh"}}, C.adhoc.mixin_parameters )
|
228
|
-
assert_equal( {M=>{:p => "many"}}, D.adhoc.mixin_parameters )
|
229
|
-
end
|
230
|
-
|
231
|
-
end
|
232
|
-
|
233
|
-
=end
|