glue 0.20.0 → 0.21.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.
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>