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