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.
- data/CHANGELOG +161 -110
- data/INSTALL +12 -12
- data/README +1 -1
- data/Rakefile +43 -45
- data/doc/AUTHORS +5 -5
- data/doc/LICENSE +3 -3
- data/doc/RELEASES +32 -24
- data/install.rb +7 -17
- data/lib/facet/object/alias_class.rb +12 -0
- data/lib/glue.rb +35 -35
- data/lib/glue/array.rb +46 -46
- data/lib/glue/aspects.rb +199 -209
- data/lib/glue/attribute.rb +15 -15
- data/lib/glue/autoreload.rb +1 -1
- data/lib/glue/builder.rb +48 -0
- data/lib/glue/builder/xml.rb +114 -0
- data/lib/glue/cache.rb +189 -0
- data/lib/glue/configuration.rb +108 -90
- data/lib/glue/flexob.rb +17 -17
- data/lib/glue/hash.rb +71 -71
- data/lib/glue/helper.rb +12 -12
- data/lib/glue/idgen.rb +9 -0
- data/lib/glue/idgen/md5.rb +24 -0
- data/lib/glue/idgen/sequential.rb +15 -0
- data/lib/glue/literal_method.rb +44 -0
- data/lib/glue/localization.rb +130 -0
- data/lib/glue/logger.rb +98 -98
- data/lib/glue/misc.rb +7 -7
- data/lib/glue/mixins.rb +19 -19
- data/lib/glue/number.rb +8 -8
- data/lib/glue/object.rb +2 -2
- data/lib/glue/pool.rb +43 -43
- data/lib/glue/property.rb +392 -392
- data/lib/glue/sanitize.rb +34 -34
- data/lib/glue/settings.rb +1 -1
- data/lib/glue/snapshot.rb +104 -0
- data/lib/glue/string.rb +129 -129
- data/lib/glue/time.rb +53 -53
- data/lib/glue/uri.rb +162 -162
- data/lib/glue/validation.rb +421 -421
- data/lib/vendor/blankslate.rb +53 -0
- data/test/glue/builder/tc_xml.rb +56 -0
- data/test/glue/tc_aspects.rb +90 -90
- data/test/glue/tc_attribute.rb +11 -11
- data/test/glue/tc_builder.rb +30 -0
- data/test/glue/tc_configuration.rb +97 -97
- data/test/glue/tc_flexob.rb +10 -10
- data/test/glue/tc_hash.rb +23 -23
- data/test/glue/tc_localization.rb +49 -0
- data/test/glue/tc_logger.rb +31 -31
- data/test/glue/tc_numbers.rb +9 -9
- data/test/glue/tc_property.rb +67 -67
- data/test/glue/tc_property_mixins.rb +17 -17
- data/test/glue/tc_property_type_checking.rb +13 -13
- data/test/glue/tc_strings.rb +94 -94
- data/test/glue/tc_uri.rb +65 -65
- data/test/glue/tc_validation.rb +196 -196
- metadata +26 -4
data/lib/glue/property.rb
CHANGED
@@ -21,48 +21,48 @@ module Glue
|
|
21
21
|
|
22
22
|
class Property
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
24
|
+
# If set to true, perform type checking on property set.
|
25
|
+
# Useful when debugging.
|
26
|
+
|
27
|
+
cattr_accessor :type_checking, false
|
28
|
+
|
29
|
+
# The symbol of the property.
|
30
|
+
|
31
|
+
attr_accessor :symbol
|
32
|
+
|
33
|
+
# The class of the property.
|
34
|
+
|
35
|
+
attr_accessor :klass
|
36
|
+
|
37
|
+
# Additional metadata (like sql declaration, sql index, etc)
|
38
|
+
# Here is a list of predefined metadata:
|
39
|
+
#
|
40
|
+
# [+:reader+]
|
41
|
+
# create reader?
|
42
|
+
#
|
43
|
+
# [+:writer+]
|
44
|
+
# create writer?
|
45
|
+
#
|
46
|
+
# [+:sql_index+]
|
47
|
+
# create an sql index for the column this poperty maps to?
|
48
|
+
#
|
49
|
+
# You can use this mechanism to add your own, custom,
|
50
|
+
# metadata.
|
51
|
+
|
52
|
+
attr_accessor :meta
|
53
|
+
|
54
|
+
def initialize(symbol, klass, meta = {})
|
55
|
+
@symbol, @klass = symbol, klass
|
56
|
+
@meta = meta
|
57
|
+
end
|
58
|
+
|
59
|
+
def ==(other)
|
60
|
+
return @symbol == other.symbol
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
return @symbol.to_s
|
65
|
+
end
|
66
66
|
|
67
67
|
end
|
68
68
|
|
@@ -70,241 +70,241 @@ end
|
|
70
70
|
|
71
71
|
module PropertyUtils
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
73
|
+
# Add accessors to the properties to the given target
|
74
|
+
# (Module or Class). For simplicity also create the
|
75
|
+
# meta accessors.
|
76
|
+
#
|
77
|
+
# [+target+]
|
78
|
+
# The target class or module
|
79
|
+
#--
|
80
|
+
# gmosx: Perhaps we 'll optimize this in the future.
|
81
|
+
#++
|
82
|
+
|
83
|
+
def self.enchant(target, force = false)
|
84
|
+
unless target.instance_variables.include?('@__props')
|
85
|
+
# FIXME: should be thread safe here!
|
86
|
+
target.instance_variable_set('@__meta', Flexob.new)
|
87
|
+
target.instance_variable_set('@__props', SafeArray.new)
|
88
|
+
|
89
|
+
# gmosx: Ruby surprises and amazes me! We are in the Metaclass
|
90
|
+
# when defining methods and attributes so @__props is really
|
91
|
+
# a class scoped variable that unlike @@__props is not shared
|
92
|
+
# through the hierarchy.
|
93
|
+
|
94
|
+
target.module_eval %{
|
95
|
+
def self.__props
|
96
|
+
@__props
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.properties
|
100
|
+
@__props
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.__props=(props)
|
104
|
+
@__props = props
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.__meta
|
108
|
+
@__meta
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.__meta=(meta)
|
112
|
+
@__meta = meta
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.metadata
|
116
|
+
@__meta
|
117
|
+
end
|
118
|
+
}
|
119
|
+
|
120
|
+
if target.is_a?(Class)
|
121
|
+
|
122
|
+
# Add some extra code to append features to
|
123
|
+
# subclasses.
|
124
|
+
|
125
|
+
target.module_eval %{
|
126
|
+
def self.inherited(child)
|
127
|
+
Glue::PropertyUtils.enchant(child)
|
128
|
+
Glue::PropertyUtils.copy_props(self, child)
|
129
|
+
# gmosx: We have to define @@__props first to avoid
|
130
|
+
# reusing the hash from the module. super must stay
|
131
|
+
# at the end.
|
132
|
+
super
|
133
|
+
end
|
134
|
+
}
|
135
|
+
|
136
|
+
else
|
137
|
+
|
138
|
+
# Add some extra code for modules to append
|
139
|
+
# their features to classes that include it.
|
140
|
+
|
141
|
+
target.module_eval %{
|
142
|
+
def self.append_features(base)
|
143
|
+
# gmosx: We have to define @@__props first to avoid
|
144
|
+
# reusing the hash from the module. super must stay
|
145
|
+
# at the end.
|
146
|
+
Glue::PropertyUtils.copy_features(self, base)
|
147
|
+
super
|
148
|
+
end
|
149
|
+
}
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Copy properties from src (Module or Class) to dest.
|
156
|
+
|
157
|
+
def self.copy_props(src, dest)
|
158
|
+
src.__props.each do |p|
|
159
|
+
add_prop(dest, p)
|
160
|
+
end
|
161
|
+
|
162
|
+
# copy the metadata.
|
163
|
+
src.__meta.each do |k, val|
|
164
|
+
if val.is_a?(TrueClass)
|
165
|
+
dest.__meta[k] = val
|
166
|
+
else
|
167
|
+
dest.__meta[k] = val.dup
|
168
|
+
end
|
169
|
+
# val.each { |v| dest.meta(k, v) } if val
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Add the property to the target (Class or Module)
|
174
|
+
|
175
|
+
def self.add_prop(target, prop)
|
176
|
+
if idx = target.__props.index(prop)
|
177
|
+
# override in case of duplicates. Keep the order of the props.
|
178
|
+
target.__props[idx] = prop
|
179
|
+
else
|
180
|
+
target.__props << prop
|
181
|
+
end
|
182
|
+
|
183
|
+
# Store the property in the :props_and_relations
|
184
|
+
# metadata array.
|
185
|
+
|
186
|
+
target.meta :props_and_relations, prop
|
187
|
+
|
188
|
+
# Precompile the property read/write methods
|
189
|
+
|
190
|
+
s, klass = prop.symbol, prop.klass
|
191
|
+
|
192
|
+
if prop.meta[:reader]
|
193
|
+
target.module_eval %{
|
194
|
+
def #{s}
|
195
|
+
return @#{s}
|
196
|
+
end
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
# gmosx: __force_xxx reuses xxx= to allow for easier
|
201
|
+
# overrides.
|
202
|
+
|
203
|
+
if prop.meta[:writer]
|
204
|
+
target.module_eval %{
|
205
|
+
#{prop_setter(prop)}
|
206
|
+
|
207
|
+
def __force_#{s}(val)
|
208
|
+
self.#{s}=(} + case klass.name
|
209
|
+
when Fixnum.name
|
210
|
+
"val.to_i()"
|
211
|
+
when String.name
|
212
|
+
"val.to_s()"
|
213
|
+
when Float.name
|
214
|
+
"val.to_f()"
|
215
|
+
when Time.name
|
216
|
+
"Time.parse(val.to_s())"
|
217
|
+
when TrueClass.name, FalseClass.name
|
218
|
+
"val.to_i() > 0"
|
219
|
+
else
|
220
|
+
"val"
|
221
|
+
end + %{)
|
222
|
+
end
|
223
|
+
}
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Generates the property setter code. Can be overriden
|
228
|
+
# to support extra functionality (example: markup)
|
229
|
+
|
230
|
+
def self.prop_setter(prop)
|
231
|
+
s = prop.symbol
|
232
|
+
|
233
|
+
code = %{
|
234
|
+
def #{s}=(val)
|
235
|
+
}
|
236
|
+
|
237
|
+
if Glue::Property.type_checking
|
238
|
+
code << %{
|
239
|
+
unless #{prop.klass} == val.class
|
240
|
+
raise "Invalid type, expected '#{prop.klass}', is '\#\{val.class\}'."
|
241
|
+
end
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
code << %{
|
246
|
+
@#{s} = val
|
247
|
+
end
|
248
|
+
}
|
249
|
+
|
250
|
+
return code
|
251
|
+
end
|
252
|
+
|
253
|
+
# Get the property metadata for the given symbol.
|
254
|
+
|
255
|
+
def self.get_prop(klass, sym)
|
256
|
+
return klass.__props.find { |p| p.symbol == sym }
|
257
|
+
end
|
258
|
+
|
259
|
+
# Include meta-language mixins
|
260
|
+
|
261
|
+
def self.include_meta_mixins(target)
|
262
|
+
target.module_eval %{ include Glue::Validation } if defined?(Glue::Validation)
|
263
|
+
# gmosx: TODO, make Og::MetaLanguage equivalent to Validation.
|
264
|
+
# target.module_eval %{ extend Og::MetaLanguage } if defined?(Og::MetaLanguage)
|
265
|
+
target.module_eval %{ include Glue::Aspects } if defined?(Glue::Aspects)
|
266
|
+
target.send(:include, Og::EntityMixin) if defined?(Og::EntityMixin)
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.copy_features(this, other)
|
270
|
+
Glue::PropertyUtils.enchant(other)
|
271
|
+
Glue::PropertyUtils.copy_props(this, other)
|
272
|
+
Glue::PropertyUtils.include_meta_mixins(other)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Resolves the parameters passed to the propxxx macros
|
276
|
+
# to generate the meta, klass and symbols variables. This
|
277
|
+
# way the common functionality is factored out.
|
278
|
+
#
|
279
|
+
# [+params+]
|
280
|
+
# The params to resolve.
|
281
|
+
# [+one_symbol+]
|
282
|
+
# If true, only resolves one symbol (used in prop).
|
283
|
+
|
284
|
+
def self.resolve_prop_params(*params)
|
285
|
+
meta = {}
|
286
|
+
klass = Object
|
287
|
+
symbols = []
|
288
|
+
|
289
|
+
for param in params.flatten
|
290
|
+
if param.is_a?(Class)
|
291
|
+
klass = param
|
292
|
+
elsif param.is_a?(Symbol)
|
293
|
+
symbols << param
|
294
|
+
elsif param.is_a?(TrueClass) or param.is_a?(TrueClass)
|
295
|
+
writer = param
|
296
|
+
elsif param.is_a?(Hash)
|
297
|
+
# the meta hash.
|
298
|
+
meta.update(param) { |k, a, b| [a,b].join(' ') }
|
299
|
+
else
|
300
|
+
raise 'Error when defining property!'
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
raise 'No symbols provided!' if symbols.empty?
|
305
|
+
|
306
|
+
return meta, klass, symbols
|
307
|
+
end
|
308
308
|
|
309
309
|
end
|
310
310
|
|
@@ -312,121 +312,121 @@ end
|
|
312
312
|
|
313
313
|
class Module
|
314
314
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
315
|
+
# Define a property (== typed attribute)
|
316
|
+
# This works like Ruby's standard attr method, ie creates
|
317
|
+
# only one property.
|
318
|
+
#
|
319
|
+
# Use the prop_reader, prop_writer, prop_accessor methods
|
320
|
+
# for multiple properties.
|
321
|
+
#
|
322
|
+
# === Examples
|
323
|
+
#
|
324
|
+
# prop String, :name, :sql => "char(32), :sql_index => "name(32)"
|
325
|
+
# --> creates only writer.
|
326
|
+
# prop Fixnum, :oid, writer = true, :sql => "integer PRIMARY KEY"
|
327
|
+
# --> creates reader and writer.
|
328
|
+
|
329
|
+
def prop(*params)
|
330
|
+
meta, klass, symbols = Glue::PropertyUtils.resolve_prop_params(params)
|
331
|
+
symbol = symbols.first
|
332
|
+
|
333
|
+
Glue::PropertyUtils.enchant(self)
|
334
|
+
|
335
|
+
property = Glue::Property.new(symbol, klass, meta)
|
336
|
+
|
337
|
+
reader = meta[:reader] || true
|
338
|
+
writer = writer || meta[:writer] || false
|
339
|
+
|
340
|
+
meta[:reader] = true if meta[:reader].nil?
|
341
|
+
if defined?(writer)
|
342
|
+
meta[:writer] = writer
|
343
|
+
else
|
344
|
+
meta[:writer] = true if meta[:writer].nil?
|
345
|
+
end
|
346
|
+
|
347
|
+
Glue::PropertyUtils.add_prop(self, property)
|
348
|
+
|
349
|
+
# gmosx: should be placed AFTER enchant!
|
350
|
+
|
351
|
+
Glue::PropertyUtils.include_meta_mixins(self)
|
352
|
+
end
|
353
|
+
|
354
|
+
# Helper method. Accepts a collection of symbols and generates
|
355
|
+
# properties. Only generates reader.
|
356
|
+
#
|
357
|
+
# Example:
|
358
|
+
# prop_reader String, :name, :title, :body, :sql => "char(32)"
|
359
|
+
|
360
|
+
def prop_reader(*params)
|
361
|
+
meta, klass, symbols = Glue::PropertyUtils.resolve_prop_params(params)
|
362
|
+
|
363
|
+
meta[:reader] = true
|
364
|
+
meta[:writer] = false
|
365
|
+
|
366
|
+
for symbol in symbols
|
367
|
+
prop(klass, symbol, meta)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
# Helper method. Accepts a collection of symbols and generates
|
372
|
+
# properties. Only generates writer.
|
373
|
+
#
|
374
|
+
# Example:
|
375
|
+
# prop_writer String, :name, :title, :body, :sql => "char(32)"
|
376
|
+
|
377
|
+
def prop_writer(*params)
|
378
|
+
meta, klass, symbols = Glue::PropertyUtils.resolve_prop_params(params)
|
379
|
+
|
380
|
+
meta[:reader] = false
|
381
|
+
meta[:writer] = true
|
382
|
+
|
383
|
+
for symbol in symbols
|
384
|
+
prop(klass, symbol, meta)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# Helper method. Accepts a collection of symbols and generates
|
389
|
+
# properties. Generates reader and writer.
|
390
|
+
#
|
391
|
+
# Example:
|
392
|
+
# prop_accessor String, :name, :title, :body, :sql => "char(32)"
|
393
|
+
|
394
|
+
def prop_accessor(*params)
|
395
|
+
meta, klass, symbols = Glue::PropertyUtils.resolve_prop_params(params)
|
396
|
+
|
397
|
+
meta[:reader] = true
|
398
|
+
meta[:writer] = true
|
399
|
+
|
400
|
+
for symbol in symbols
|
401
|
+
prop(klass, symbol, meta)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
alias_method :property, :prop_accessor
|
405
|
+
|
406
|
+
# Attach metadata.
|
407
|
+
# Guard against duplicates, no need to keep order.
|
408
|
+
# This method uses closures :)
|
409
|
+
#--
|
410
|
+
# gmosx: crappy implementation, recode.
|
411
|
+
#++
|
412
|
+
|
413
|
+
def meta(key, *val)
|
414
|
+
Glue::PropertyUtils.enchant(self)
|
415
|
+
|
416
|
+
if val.empty?
|
417
|
+
self.module_eval %{
|
418
|
+
@__meta[key] = true
|
419
|
+
}
|
420
|
+
else
|
421
|
+
val = val.first if val.size == 1
|
422
|
+
|
423
|
+
self.module_eval %{
|
424
|
+
@__meta[key] ||= []
|
425
|
+
@__meta[key].delete_if { |v| val == v }
|
426
|
+
@__meta[key] << val
|
427
|
+
}
|
428
|
+
end
|
429
|
+
end
|
430
430
|
|
431
431
|
end
|
432
432
|
|