glue 0.29.0 → 0.30.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/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
|