glue 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG +161 -110
  2. data/INSTALL +12 -12
  3. data/README +1 -1
  4. data/Rakefile +43 -45
  5. data/doc/AUTHORS +5 -5
  6. data/doc/LICENSE +3 -3
  7. data/doc/RELEASES +32 -24
  8. data/install.rb +7 -17
  9. data/lib/facet/object/alias_class.rb +12 -0
  10. data/lib/glue.rb +35 -35
  11. data/lib/glue/array.rb +46 -46
  12. data/lib/glue/aspects.rb +199 -209
  13. data/lib/glue/attribute.rb +15 -15
  14. data/lib/glue/autoreload.rb +1 -1
  15. data/lib/glue/builder.rb +48 -0
  16. data/lib/glue/builder/xml.rb +114 -0
  17. data/lib/glue/cache.rb +189 -0
  18. data/lib/glue/configuration.rb +108 -90
  19. data/lib/glue/flexob.rb +17 -17
  20. data/lib/glue/hash.rb +71 -71
  21. data/lib/glue/helper.rb +12 -12
  22. data/lib/glue/idgen.rb +9 -0
  23. data/lib/glue/idgen/md5.rb +24 -0
  24. data/lib/glue/idgen/sequential.rb +15 -0
  25. data/lib/glue/literal_method.rb +44 -0
  26. data/lib/glue/localization.rb +130 -0
  27. data/lib/glue/logger.rb +98 -98
  28. data/lib/glue/misc.rb +7 -7
  29. data/lib/glue/mixins.rb +19 -19
  30. data/lib/glue/number.rb +8 -8
  31. data/lib/glue/object.rb +2 -2
  32. data/lib/glue/pool.rb +43 -43
  33. data/lib/glue/property.rb +392 -392
  34. data/lib/glue/sanitize.rb +34 -34
  35. data/lib/glue/settings.rb +1 -1
  36. data/lib/glue/snapshot.rb +104 -0
  37. data/lib/glue/string.rb +129 -129
  38. data/lib/glue/time.rb +53 -53
  39. data/lib/glue/uri.rb +162 -162
  40. data/lib/glue/validation.rb +421 -421
  41. data/lib/vendor/blankslate.rb +53 -0
  42. data/test/glue/builder/tc_xml.rb +56 -0
  43. data/test/glue/tc_aspects.rb +90 -90
  44. data/test/glue/tc_attribute.rb +11 -11
  45. data/test/glue/tc_builder.rb +30 -0
  46. data/test/glue/tc_configuration.rb +97 -97
  47. data/test/glue/tc_flexob.rb +10 -10
  48. data/test/glue/tc_hash.rb +23 -23
  49. data/test/glue/tc_localization.rb +49 -0
  50. data/test/glue/tc_logger.rb +31 -31
  51. data/test/glue/tc_numbers.rb +9 -9
  52. data/test/glue/tc_property.rb +67 -67
  53. data/test/glue/tc_property_mixins.rb +17 -17
  54. data/test/glue/tc_property_type_checking.rb +13 -13
  55. data/test/glue/tc_strings.rb +94 -94
  56. data/test/glue/tc_uri.rb +65 -65
  57. data/test/glue/tc_validation.rb +196 -196
  58. metadata +26 -4
data/lib/glue/aspects.rb CHANGED
@@ -5,20 +5,20 @@ module Glue
5
5
  # An Aspect is a class that defines advices.
6
6
 
7
7
  class Aspect
8
- class << self
9
- def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
10
- target.send(:include, Aspects) unless target.ancestors.include?(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, Aspects) unless target.ancestors.include?(Aspects)
19
- target.wrap(self, :pre => pre, :post => post)
20
- end
21
- alias_method :observe, :wrap
8
+ class << self
9
+ def wrap(target, methods = target.instance_methods, pre = :pre, post = :post)
10
+ target.send(:include, Aspects) unless target.ancestors.include?(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, Aspects) unless target.ancestors.include?(Aspects)
19
+ target.wrap(self, :pre => pre, :post => post)
20
+ end
21
+ alias_method :observe, :wrap
22
22
  end
23
23
 
24
24
  # Add support for Aspect Oriented Programming (AOP).
@@ -26,208 +26,198 @@ end
26
26
  # === Examples
27
27
  #
28
28
  # class Controller
29
- # pre :force_login, :where => :prepend
30
- # wrap Benchmark, :on => :index
31
- # post :taraa, :on => login
29
+ # pre :force_login, :where => :prepend
30
+ # wrap Benchmark, :on => :index
31
+ # post :taraa, :on => login
32
32
  # end
33
33
  #
34
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 }
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
38
  # end
39
39
 
40
40
  module Aspects
41
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
- # Include Modules that define advices.
69
-
70
- def self.include_advice_modules(target)
71
- for a in target.advices
72
- if a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
73
- target.module_eval %{ include #{a.code} }
74
-
75
- options = a.options.reject { |k,v| k == :pre || k == :post }
76
-
77
- method = (a.options[:pre] || 'pre').to_s
78
- if a.code.instance_methods.include?(method)
79
- options.update(:where => :prepend, :join => :pre)
80
- target.advices << Advice.new(method, options)
81
- end
82
-
83
- method = (a.options[:post] || 'post').to_s
84
- if a.code.instance_methods.include?(method)
85
- options.update(:where => :append, :join => :post)
86
- target.advices << Advice.new(method, options)
87
- end
88
- end
89
- end
90
-
91
- # Remove the original advice.
92
-
93
- target.advices.delete_if do |a|
94
- a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
95
- end
96
- end
97
-
98
- # Generates the code to call the aspects.
99
-
100
- def self.gen_advice_code(method, advices, join = :pre) # :nodoc:
101
- code = ''
102
-
103
- advices.each_with_index do |advice, idx|
104
- o = options = advice.options
105
-
106
- if only = options[:only] || options[:on]
107
- next unless [only].flatten.include?(method.to_sym)
108
- elsif except = options[:except]
109
- next if [except].flatten.include?(method.to_sym)
110
- end
111
-
112
- advice = advice.code
113
-
114
- if advice.is_a?(Symbol) or advice.is_a?(String)
115
- next if o[:join] != join
116
- code << "#{advice}; "
117
- elsif advice.respond_to?('call')
118
- next if o[:join] != join
119
- code << "self.class.advices[#{idx}].code.call(self); "
120
- elsif advice.is_a?(Class)
121
- if advice.class.ancestors.include?(Class)
122
- if m = o[join] and advice.methods.include?(m.to_s)
123
- code << "#{advice}.#{m}(self); "
124
- end
125
- else
126
- # Module, allready handled.
127
- end
128
- else
129
- if m = o[join] and advice.methods.include?(m.to_s)
130
- code << "self.class.advices[#{idx}].code.#{m}(self); "
131
- end
132
- end
133
- end
134
-
135
- return code
136
- end
137
-
138
- def self.append_features(base)
139
- super
140
- base.extend(ClassMethods)
141
-
142
- base.module_eval %{
143
- Glue::PropertyUtils.enchant(self)
144
-
145
- def self.advices
146
- __meta[:advices] || []
147
- end
148
-
149
- def self.advices=(advices)
150
- __meta[:advices] = advices
151
- end
152
-
153
- #def self.inherited(child)
154
- # super
155
- # child.send(:include, Aspects)
156
- #end
157
- #
158
- #def self.append_features(base)
159
- # super
160
- # base.send(:include, Aspects)
161
- #end
162
- }
163
- end
164
-
165
- module ClassMethods
166
-
167
- # Add a pre (before) advice.
168
-
169
- def pre(*args, &block)
170
- o = options = {
171
- :join => :pre,
172
- :where => :prepend,
173
- }
174
- options.update(args.pop) if args.last.is_a?(Hash)
175
-
176
- if block_given?
177
- advices = [ Advice.new(block, options) ]
178
- else
179
- advices = args.collect { |a| Advice.new(a, options) }
180
- end
181
-
182
- if options[:where] == :prepend
183
- self.advices = advices + self.advices
184
- else
185
- self.advices = self.advices + advices
186
- end
187
- end
188
- alias_method :before, :pre
189
-
190
- # Add a post (after) advice.
191
-
192
- def post(*args, &block)
193
- o = options = {
194
- :join => :post,
195
- :where => :append,
196
- }
197
- options.update(args.pop) if args.last.is_a?(Hash)
198
-
199
- if block_given?
200
- advices = [ Advice.new(block, options) ]
201
- else
202
- advices = args.collect { |a| Advice.new(a, options) }
203
- end
204
-
205
- if options[:where] == :prepend
206
- self.advices = advices + self.advices
207
- else
208
- self.advices = self.advices + advices
209
- end
210
- end
211
- alias_method :after, :post
212
-
213
- # Add a wrap (arround) aspect. An aspect is a class that
214
- # responds to the before and after advices.
215
-
216
- def wrap(*args)
217
- o = options = {
218
- :pre => :pre,
219
- :post => :post
220
- }
221
- options.update(args.pop) if args.last.is_a?(Hash)
222
-
223
- for aspect in args
224
- self.advices << Advice.new(aspect, options)
225
- end
226
- end
227
- alias_method :around, :wrap
228
- alias_method :observer, :wrap
229
-
230
- end
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
+ # Include Modules that define advices.
69
+
70
+ def self.include_advice_modules(target)
71
+ for a in target.advices
72
+ if a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
73
+ target.module_eval %{ include #{a.code} }
74
+
75
+ options = a.options.reject { |k,v| k == :pre || k == :post }
76
+
77
+ method = (a.options[:pre] || 'pre').to_s
78
+ if a.code.instance_methods.include?(method)
79
+ options.update(:where => :prepend, :join => :pre)
80
+ target.advices << Advice.new(method, options)
81
+ end
82
+
83
+ method = (a.options[:post] || 'post').to_s
84
+ if a.code.instance_methods.include?(method)
85
+ options.update(:where => :append, :join => :post)
86
+ target.advices << Advice.new(method, options)
87
+ end
88
+ end
89
+ end
90
+
91
+ # Remove the original advice.
92
+
93
+ target.advices.delete_if do |a|
94
+ a.code.is_a?(Module) and (!a.code.class.ancestors.include?(Class))
95
+ end
96
+ end
97
+
98
+ # Generates the code to call the aspects.
99
+
100
+ def self.gen_advice_code(method, advices, join = :pre) # :nodoc:
101
+ code = ''
102
+
103
+ advices.each_with_index do |advice, idx|
104
+ o = options = advice.options
105
+
106
+ if only = options[:only] || options[:on]
107
+ next unless [only].flatten.include?(method.to_sym)
108
+ elsif except = options[:except]
109
+ next if [except].flatten.include?(method.to_sym)
110
+ end
111
+
112
+ advice = advice.code
113
+
114
+ if advice.is_a?(Symbol) or advice.is_a?(String)
115
+ next if o[:join] != join
116
+ code << "#{advice}; "
117
+ elsif advice.respond_to?('call')
118
+ next if o[:join] != join
119
+ code << "self.class.advices[#{idx}].code.call(self); "
120
+ elsif advice.is_a?(Class)
121
+ if advice.class.ancestors.include?(Class)
122
+ if m = o[join] and advice.methods.include?(m.to_s)
123
+ code << "#{advice}.#{m}(self); "
124
+ end
125
+ else
126
+ # Module, allready handled.
127
+ end
128
+ else
129
+ if m = o[join] and advice.methods.include?(m.to_s)
130
+ code << "self.class.advices[#{idx}].code.#{m}(self); "
131
+ end
132
+ end
133
+ end
134
+
135
+ return code
136
+ end
137
+
138
+ def self.append_features(base)
139
+ super
140
+ base.extend(ClassMethods)
141
+
142
+ base.module_eval %{
143
+ Glue::PropertyUtils.enchant(self)
144
+
145
+ def self.advices
146
+ __meta[:advices] || []
147
+ end
148
+
149
+ def self.advices=(advices)
150
+ __meta[:advices] = advices
151
+ end
152
+ }
153
+ end
154
+
155
+ module ClassMethods
156
+
157
+ # Add a pre (before) advice.
158
+
159
+ def pre(*args, &block)
160
+ o = options = {
161
+ :join => :pre,
162
+ :where => :prepend,
163
+ }
164
+ options.update(args.pop) if args.last.is_a?(Hash)
165
+
166
+ if block_given?
167
+ advices = [ Advice.new(block, options) ]
168
+ else
169
+ advices = args.collect { |a| Advice.new(a, options) }
170
+ end
171
+
172
+ if options[:where] == :prepend
173
+ self.advices = advices + self.advices
174
+ else
175
+ self.advices = self.advices + advices
176
+ end
177
+ end
178
+ alias_method :before, :pre
179
+
180
+ # Add a post (after) advice.
181
+
182
+ def post(*args, &block)
183
+ o = options = {
184
+ :join => :post,
185
+ :where => :append,
186
+ }
187
+ options.update(args.pop) if args.last.is_a?(Hash)
188
+
189
+ if block_given?
190
+ advices = [ Advice.new(block, options) ]
191
+ else
192
+ advices = args.collect { |a| Advice.new(a, options) }
193
+ end
194
+
195
+ if options[:where] == :prepend
196
+ self.advices = advices + self.advices
197
+ else
198
+ self.advices = self.advices + advices
199
+ end
200
+ end
201
+ alias_method :after, :post
202
+
203
+ # Add a wrap (arround) aspect. An aspect is a class that
204
+ # responds to the before and after advices.
205
+
206
+ def wrap(*args)
207
+ o = options = {
208
+ :pre => :pre,
209
+ :post => :post
210
+ }
211
+ options.update(args.pop) if args.last.is_a?(Hash)
212
+
213
+ for aspect in args
214
+ self.advices << Advice.new(aspect, options)
215
+ end
216
+ end
217
+ alias_method :around, :wrap
218
+ alias_method :observer, :wrap
219
+
220
+ end
231
221
 
232
222
  end
233
223
 
@@ -17,15 +17,15 @@
17
17
 
18
18
  class Module # :nodoc:
19
19
 
20
- # A macro that creates a reader method for class/module
21
- # attributes.
22
-
20
+ # A macro that creates a reader method for class/module
21
+ # attributes.
22
+
23
23
  def mattr_reader(*params)
24
- default = if params.last.is_a?(Symbol) then nil else params.pop end
25
-
24
+ default = if params.last.is_a?(Symbol) then nil else params.pop end
25
+
26
26
  for sym in params
27
- module_eval <<-"end_eval", __FILE__, __LINE__
28
-
27
+ module_eval <<-"end_eval", __FILE__, __LINE__
28
+
29
29
  if not defined?(@@#{sym.id2name})
30
30
  @@#{sym.id2name} = #{default.inspect}
31
31
  end
@@ -39,14 +39,14 @@ class Module # :nodoc:
39
39
  end
40
40
  alias_method :cattr_reader, :mattr_reader
41
41
 
42
- # A macro that creates a writer method for class/module
43
- # attributes.
42
+ # A macro that creates a writer method for class/module
43
+ # attributes.
44
44
 
45
45
  def mattr_writer(*params)
46
- default = if params.last.is_a?(Symbol) then nil else params.pop end
47
-
46
+ default = if params.last.is_a?(Symbol) then nil else params.pop end
47
+
48
48
  for sym in params
49
- module_eval <<-"end_eval", __FILE__, __LINE__
49
+ module_eval <<-"end_eval", __FILE__, __LINE__
50
50
 
51
51
  if not defined?(@@#{sym.id2name})
52
52
  @@#{sym.id2name} = #{default.inspect.inspect}
@@ -65,15 +65,15 @@ class Module # :nodoc:
65
65
  end
66
66
  alias_method :cattr_writer, :cattr_writer
67
67
 
68
- # A macro that creates a reader and a writer method for
69
- # class/module attributes.
68
+ # A macro that creates a reader and a writer method for
69
+ # class/module attributes.
70
70
 
71
71
  def mattr_accessor(*syms)
72
72
  mattr_reader(*syms)
73
73
  mattr_writer(*syms)
74
74
  end
75
75
  alias_method :cattr_accessor, :mattr_accessor
76
-
76
+
77
77
  end
78
78
 
79
79
  # * George Moschovitis <gm@navel.gr>