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/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
@@ -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>
@@ -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