moosex 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95164f069f5f27913dfeb6140414d1b0f15e9687
4
- data.tar.gz: 8c93aee2bfaea678c830ed0a1288e170a2bc0bf2
3
+ metadata.gz: ae6315aba6d50e3443b6e0b184a3d51a4ef676d2
4
+ data.tar.gz: e80dc006c7d9ba38c22130007416ca5f29650fec
5
5
  SHA512:
6
- metadata.gz: 23c4c3ff11a33e0d034621564c0c336ce42ab71e511dd04a35cb8a23e2292ac41f80097c9071f61f163461c9f0e98408ec98006342115fa23bb35d896935e7e4
7
- data.tar.gz: 9ee664b8973c9187a510ba14dec13fc89a4c40e3a596793f0a91233dcde4e2a6e711857941432d71ca61ad2a36dab0a03009b280112a198c3a65b1c860a1bcb5
6
+ metadata.gz: 660d4f1f3a542d7e21f66d7d8b335bfe6acb1cde810c65cf8ee37aa82227fe74185b9614a726b0e97f7d5db415182560a710cb072264cae6c7b7dce4b60b9d4c
7
+ data.tar.gz: 0f8071f6fcec75b2ef8d95e0dc2e02388abb45b7fd82aad2aec5b8eeb7be5b759ac02a2862d8f939fe7fe51c81afc326c0843772422bbc0ba577cf9d93fb68b6
data/Changelog CHANGED
@@ -1,7 +1,12 @@
1
+ 0.0.18 - 2013-02-12
2
+ - better meta #58
3
+ - reduce internal complexity #51, #70
4
+ - meta now has __moosex__ prefix #55
5
+
1
6
  0.0.17 - 2013-02-11
2
- - has now support an override option #56
3
- - has now support a doc option #57
4
- - has now should not require :is => default is :rw #54
7
+ - has now support an override option #56
8
+ - has now support a doc option #57
9
+ - has now should not require :is => default is :rw #54
5
10
  - add weak ref support #49
6
11
 
7
12
  0.0.16 - 2013-02-07
@@ -15,63 +20,63 @@
15
20
  - add init method to enable warnings and exceptions #43
16
21
 
17
22
  0.0.14 - 2013-02-05
18
- - roles with around/before/after basic support #41
23
+ - roles with around/before/after basic support #41
19
24
 
20
25
  0.0.13 - 2013-02-05
21
- - change around to receive a lambda #42
26
+ - change around to receive a lambda #42
22
27
 
23
28
  0.0.12 - 2013-02-05
24
- - basic support override attributes #19
25
- - basic support to roles #17
29
+ - basic support override attributes #19
30
+ - basic support to roles #17
26
31
 
27
32
  0.0.11 - 2013-02-04
28
- - basic support to after/before/around #12
29
- - improve exception #15
30
- - improve type system via MooseX::Types #16
31
-
33
+ - basic support to after/before/around #12
34
+ - improve exception #15
35
+ - improve type system via MooseX::Types #16
36
+
32
37
  0.0.10 - 2014-02-03
33
- - improve readme
38
+ - improve readme
34
39
  - BUILDARGS should accept different signatures #36
35
40
  - clearer create by default clear_#{attr_name}! public method
36
41
  - add attr :private #35
37
42
  - methods predicate, clearer and handles are no longer singleton methods #34
38
43
 
39
44
  0.0.9 - 2014-02-02
40
- - support to BUILD and BUILDARGS #5 and #6
41
- - support to trigger #7
42
- - support to coerce #8
45
+ - support to BUILD and BUILDARGS #5 and #6
46
+ - support to trigger #7
47
+ - support to coerce #8
43
48
 
44
49
  0.0.8 - 2014-02-01
45
50
  - should support init_arg option in attr #14
46
- - support lazy attributes / builder #4
47
- - support a custom name for getter / setter #9
48
-
51
+ - support lazy attributes / builder #4
52
+ - support a custom name for getter / setter #9
53
+
49
54
  0.0.7 - 2014-02-01
50
55
  - add min version of ruby should be 2.0.x
51
56
 
52
57
  0.0.6 - 2014-02-01
53
- - fix bug when extends subclass, now it is safe #18
54
- - required attr with default value will no longer throw exception #30
55
- - supports handles for: single method, array, Class or Module #27
58
+ - fix bug when extends subclass, now it is safe #18
59
+ - required attr with default value will no longer throw exception #30
60
+ - supports handles for: single method, array, Class or Module #27
56
61
 
57
62
  0.0.5 - 2014-01-31
58
- - should support handles #13 (partial)
63
+ - should support handles #13 (partial)
59
64
 
60
65
  0.0.4 - 2014-01-31
61
- - fix an issue related to ruby > 1.9.2
66
+ - fix an issue related to ruby > 1.9.2
62
67
 
63
68
  0.0.3 - 2014-01-31
64
- - add support to clearer #26
65
- - add support to predicate #11
66
- - add support to handle more than one attribute #2
67
- - small improvements
69
+ - add support to clearer #26
70
+ - add support to predicate #11
71
+ - add support to handle more than one attribute #2
72
+ - small improvements
68
73
 
69
74
  0.0.2 - 2014-01-31
70
- - fix one important bug, not it is possible use in more than one class
71
- - add require option
72
- - supports :ro, :rw, :rwp ( read-only, read-write and read-write-private) options
73
- - supports default value as lambda or constant
74
- - supports isa as class/module name or lambda
75
+ - fix one important bug, not it is possible use in more than one class
76
+ - add require option
77
+ - supports :ro, :rw, :rwp ( read-only, read-write and read-write-private) options
78
+ - supports default value as lambda or constant
79
+ - supports isa as class/module name or lambda
75
80
 
76
81
  0.0.1 - 2014-01-31
77
- - first release
82
+ - first release
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moosex (0.0.17)
4
+ moosex (0.0.18)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -474,7 +474,7 @@ Optional.
474
474
 
475
475
  ## doc => String
476
476
 
477
- You can add a string metadata about the attribute. It will be stored, and you can use this in a near future.
477
+ You can add a string metadata about the attribute. If you include MooseX with `meta: true` you can inspect the list of attributes and documentation.
478
478
 
479
479
  Optional.
480
480
 
@@ -557,8 +557,48 @@ The around hook is agressive: it will substitute the original method for a lambd
557
557
 
558
558
  it is useful to manipulate the return value or argument list, add a begin/rescue block, aditional validations, etc, if you need.
559
559
 
560
+ ## MooseX.init
561
+
562
+ The init method is useful to change some behavior of MooseX on the fly.
563
+
564
+ ### warnings => true|false
565
+
566
+ will disable all warnings from MooseX. It is Global. Default is true.
567
+
568
+ ```ruby
569
+ class X
570
+ include MooseX.init(warnings: false)
571
+ ```
572
+
573
+ ### fatal => true|false
574
+
575
+ all warnings will raise exceptions. It is Global. Default is false
576
+
577
+ ```ruby
578
+ class X
579
+ include MooseX.init(fatal: true)
580
+ ```
581
+
582
+ ### meta => Symbol|String|true|false
583
+
584
+ will expose an alias for the class metadata in the class. If you use true, we will generate a method 'meta', if you provide a Symbol or String we will create a method with same name.
585
+
586
+ ```ruby
587
+ class X
588
+ include MooseX.init(meta: true)
589
+
590
+ has :foo, { is: :rw, doc => "this is foo"}
591
+ end
592
+
593
+ X.meta.info # will return { :foo => "this is foo" }
594
+ ```
595
+
596
+ The metadata has two public methods: attrs and info. Be careful.
597
+
560
598
  ## MooseX::Types
561
599
 
600
+ **WARNING** This will be extract for a parallel project/ gem!
601
+
562
602
  MooseX has a built-in type system to be helpful in many circunstances. How many times you need check if some argument is_a? Something? Or it respond_to? :some_method ? Now it is over. If you include the **MooseX::Types** module in your MooseX class you can use:
563
603
 
564
604
  ### isAny
@@ -860,6 +900,8 @@ ex3 = BuildArgsExample2.new() # x == 4, y == 8
860
900
 
861
901
  ## EVENTS
862
902
 
903
+ **WARNING** This will be extract for a parallel project/ gem!
904
+
863
905
  MooseX has a built-in event system, and it should be useful if you want to avoid after/before hooks ( depends of what is your problem ).
864
906
 
865
907
  ```ruby
@@ -4,21 +4,26 @@
4
4
  # Author:: Tiago Peczenyj (mailto:tiago.peczenyj@gmail.com)
5
5
  # Copyright:: Copyright (c) 2014 Tiago Peczenyj
6
6
  # License:: MIT
7
- #
7
+
8
8
  require "moosex/version"
9
9
  require "moosex/types"
10
+ require "moosex/exceptions"
11
+ require "moosex/meta"
12
+ require "moosex/core"
13
+ require "moosex/attribute"
10
14
  require "weakref"
11
15
 
12
16
  module MooseX
17
+ @@ALIAS = nil
13
18
  @@MOOSEX_WARNINGS = true
14
19
  @@MOOSEX_FATAL = false
15
-
16
- class FatalError < StandardError
17
- end
18
-
20
+
19
21
  def self.warn(x, *c)
20
- raise FatalError, "[MooseX] exception: #{x}",*c if @@MOOSEX_FATAL
21
- Kernel.warn("[MooseX] warning: #{x}") if @@MOOSEX_WARNINGS
22
+ if @@MOOSEX_FATAL
23
+ raise FatalError, "[MooseX] exception: #{x}",*c
24
+ elsif @@MOOSEX_WARNINGS
25
+ Kernel.warn("[MooseX] warning: #{x}")
26
+ end
22
27
  end
23
28
 
24
29
  def self.init(args={})
@@ -29,648 +34,76 @@ module MooseX
29
34
  if args.has_key? :fatal
30
35
  @@MOOSEX_FATAL = !! args[:fatal]
31
36
  end
32
-
33
- self
34
- end
35
-
36
- class RequiredMethodNotFoundError < NameError
37
- end
38
37
 
39
- def MooseX.included(c)
40
-
41
- c.extend(MooseX::Core)
42
-
43
- def c.init(*args)
44
- __meta.roles.each{|role| role.call(*args)}
45
-
46
- self
38
+ if args.has_key?(:meta) && !! args[:meta]
39
+ @@ALIAS = (args[:meta].is_a?(TrueClass))? :meta : args[:meta]
47
40
  end
48
41
 
49
- def c.included(x)
50
-
51
- MooseX.included(x)
52
- x.__meta.load_from(self.__meta)
53
-
54
- return unless x.is_a? Class
55
-
56
- x.__meta.load_hooks(self.__meta)
57
- self.__meta.init_klass(x)
58
-
59
- x.__meta.requires.each do |method|
60
- unless x.public_instance_methods.include? method
61
- MooseX.warn "you must implement method '#{method}' in #{x} #{x.class}: required"# if $MOOSEX_DEBUG
62
- end
63
- end
64
- end
65
-
66
- meta = MooseX::Meta.new
67
-
68
- unless c.respond_to? :__meta
69
- c.class_exec do
70
- define_singleton_method(:__meta) { meta }
71
- define_singleton_method(:__meta_define_method) do |method_name, &proc|
72
- define_method(method_name, proc)
73
- end
74
- end
75
- end
76
-
77
- def initialize(*args)
78
- if self.respond_to? :BUILDARGS
79
- args = self.BUILDARGS(*args)
80
- else
81
- args = args[0]
82
- end
83
-
84
- self.class.__meta().init(self, args || {})
85
-
86
- self.BUILD() if self.respond_to? :BUILD
87
- end
88
-
89
- def c.inherited(subclass)
90
- subclass.class_exec do
91
- old_meta = subclass.__meta
92
-
93
- meta = MooseX::Meta.new(old_meta)
94
-
95
- define_singleton_method(:__meta) { meta }
96
- end
97
- end
98
-
42
+ self
99
43
  end
100
-
101
- class Meta
102
- attr_reader :attrs, :requires, :before, :after, :around, :roles
103
44
 
104
- def initialize(old_meta=nil)
105
- @initialized = false
106
- @attrs = {}
107
- @requires = []
108
- @roles = []
109
- @before = Hash.new { |hash, key| hash[key] = [] }
110
- @after = Hash.new { |hash, key| hash[key] = [] }
111
- @around = Hash.new { |hash, key| hash[key] = [] }
45
+ def initialize(*args)
46
+ if self.respond_to? :BUILDARGS
47
+ args = self.BUILDARGS(*args)
48
+ else
49
+ args = args[0]
50
+ end
112
51
 
113
- if old_meta
114
- old_meta.attrs.each_pair do |key, value|
115
- @attrs[key] = value.clone
116
- end
117
- @requires = old_meta.requires.clone
118
- end
119
- end
52
+ self.class.__moosex__meta.init(self, args || {})
120
53
 
121
- def load_from(other_meta)
122
- other_meta.attrs.each_pair do |key, value|
123
- @attrs[key] = value.clone
124
- end
125
- @requires += other_meta.requires
126
- end
127
-
128
- def load_hooks(other_meta)
129
- other_meta.before.each_pair do |m, b|
130
- @before[m] += b.clone
131
- end
132
- other_meta.after.each_pair do |m, b|
133
- @after[m] += b.clone
134
- end
135
- other_meta.around.each_pair do |m, b|
136
- @around[m] += b.clone
137
- end
138
- end
54
+ self.BUILD() if self.respond_to? :BUILD
55
+ end
139
56
 
140
- def add(attr)
141
- if @attrs.has_key?(attr.attr_symbol) && ! attr.override
142
- raise FatalError, "#{attr.attr_symbol} already exists, you should specify override: true"
143
- end
144
- @attrs[attr.attr_symbol] = attr
145
- end
57
+ def MooseX.included(class_or_module)
146
58
 
147
- def add_requires(method)
148
- @requires << method
149
- end
59
+ class_or_module.extend(MooseX::Core)
150
60
 
151
- def add_before(method_name, block)
152
- @before[method_name] << block.clone
153
- end
61
+ unless class_or_module.respond_to? :__moosex__meta
62
+ meta = MooseX::Meta.new
154
63
 
155
- def add_after(method_name, block)
156
- @after[method_name] << block.clone
157
- end
64
+ class_or_module.define_singleton_method(:__moosex__meta) { meta }
158
65
 
159
- def add_around(method_name, block)
160
- @around[method_name] << block.clone
161
- end
162
-
163
- def add_role(block)
164
- @roles << block
165
- end
166
-
167
- def init_klass(klass)
168
- #return if @initialized
169
-
170
- [@before.keys + @after.keys + @around.keys].flatten.uniq.each do |method_name|
171
- begin
172
- method = klass.instance_method method_name
173
- rescue => e
174
- MooseX.warn "Unable to apply hooks (after/before/around) in #{klass}::#{method_name} : #{e}" # if $MOOSEX_DEBUG
175
- next
66
+ if @@ALIAS
67
+ class_or_module.class_eval do
68
+ class_or_module.define_singleton_method(@@ALIAS) { meta }
176
69
  end
177
-
178
- before = @before[method_name]
179
- after = @after[method_name]
180
- around = @around[method_name]
181
-
182
- klass.__meta_define_method(method_name) do |*args, &proc|
183
- before.each{|b| b.call(self,*args, &proc)}
184
-
185
- original = lambda do |object, *args, &proc|
186
- method.bind(object).call(*args, &proc)
187
- end
188
-
189
- result = around.inject(original) do |lambda1, lambda2|
190
- lambda2.curry[lambda1]
191
- end.call(self, *args, &proc)
192
-
193
- after.each{|b| b.call(self,*args, &proc)}
194
-
195
- result
196
- end
197
- end
198
- end
199
-
200
- def init(object, args)
201
- @attrs.each_pair{ |symbol, attr| attr.init(object, args) }
202
-
203
- MooseX.warn "unused attributes #{args} for #{object.class}", caller unless args.empty?
204
-
205
- @requires.each do |method|
206
- unless object.respond_to? method
207
- raise RequiredMethodNotFoundError,
208
- "you must implement method '#{method}' in #{object.class}: required"
209
- end
210
- end
211
- end
212
- end
213
-
214
- module Core
215
- def on_init(&block)
216
- __meta.add_role(block)
70
+ @@ALIAS = false
71
+ end
217
72
  end
218
73
 
219
- def after(*methods_name, &block)
220
- methods_name.each do |method_name|
221
- begin
222
- method = instance_method method_name
223
-
224
- define_method method_name do |*args, &proc|
225
- result = method.bind(self).call(*args, &proc)
226
- block.call(self,*args,&proc)
227
- result
228
- end
229
- rescue => e
230
- MooseX.warn "unable to apply hook after in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
231
- __meta.add_after(method_name, block)
232
- end
233
- end
234
- end
235
-
236
- def before(*methods_name, &block)
237
- methods_name.each do |method_name|
238
- begin
239
- method = instance_method method_name
240
-
241
- define_method method_name do |*args, &proc|
242
- block.call(self,*args, &proc)
243
- method.bind(self).call(*args, &proc)
244
- end
245
- rescue => e
246
- MooseX.warn "unable to apply hook before in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
247
- __meta.add_before(method_name, block)
248
- end
249
- end
250
- end
251
-
252
- def around(*methods_name, &block)
253
- methods_name.each do |method_name|
254
- begin
255
-
256
- method = instance_method method_name
257
-
258
- code = Proc.new do | o, *a, &proc|
259
- method.bind(o).call(*a,&proc)
260
- end
261
-
262
- define_method method_name do |*args, &proc|
263
- block.call(code, self,*args, &proc)
264
- end
265
-
266
- rescue => e
267
- MooseX.warn "unable to apply hook around in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
268
- __meta.add_around(method_name, block)
269
- end
270
- end
271
- end
272
-
273
- def requires(*methods)
274
-
275
- methods.each do |method_name|
276
- __meta.add_requires(method_name)
277
- end
278
- end
279
-
280
- def has(attr_name, attr_options = {})
281
- if attr_name.is_a? Array
282
- attr_name.each do |attr|
283
- has(attr, attr_options)
284
- end
285
- elsif attr_name.is_a? Hash
286
- attr_name.each_pair do |attr, options |
287
- has(attr, options)
288
- end
289
- else
290
- attr = MooseX::Attribute.new(attr_name, attr_options, self)
291
-
292
- __meta.add(attr)
293
-
294
- attr.methods.each_pair do |method, proc|
295
- define_method method, &proc
296
- end
297
-
298
- if attr.is.eql?(:rwp)
299
- private attr.writter
300
- elsif attr.is.eql?(:private)
301
- private attr.writter
302
- private attr.reader
303
- end
304
- end
74
+ def class_or_module.init(*args)
75
+ __moosex__meta.init_roles(*args)
76
+
77
+ self
305
78
  end
306
- end
307
-
308
- class InvalidAttributeError < TypeError
309
-
310
- end
311
79
 
312
- class Attribute
313
- include MooseX::Types
80
+ def class_or_module.inherited(subclass)
81
+ old_meta = subclass.__moosex__meta
314
82
 
315
- attr_reader :attr_symbol, :is, :reader, :writter, :lazy, :builder, :methods, :override
316
- DEFAULTS= {
317
- is: :rw,
318
- weak: false,
319
- lazy: false,
320
- clearer: false,
321
- required: false,
322
- predicate: false,
323
- isa: isAny,
324
- handles: {},
325
- trigger: lambda {|object,value|}, # TODO: implement
326
- coerce: lambda {|object| object}, # TODO: implement
327
- doc: nil,
328
- override: false,
329
- }
83
+ meta = MooseX::Meta.new(old_meta)
330
84
 
331
- REQUIRED = []
332
-
333
- VALIDATE = {
334
- is: lambda do |is, field_name|
335
- unless [:rw, :rwp, :ro, :lazy, :private].include?(is)
336
- raise InvalidAttributeError, "invalid value for field '#{field_name}' is '#{is}', must be one of :private, :rw, :rwp, :ro or :lazy"
337
- end
338
- end,
339
- };
340
-
341
- COERCE = {
342
- is: lambda do |is, field_name|
343
- is.to_sym
344
- end,
345
- isa: lambda do |isa, field_name|
346
- isType(isa)
347
- end,
348
- default: lambda do |default, field_name|
349
- return default if default.is_a? Proc
350
-
351
- return lambda { default }
352
- end,
353
- required: lambda do |required, field_name|
354
- !!required
355
- end,
356
- lazy: lambda do |lazy, field_name|
357
- !!lazy
358
- end,
359
- predicate: lambda do |predicate, field_name|
360
- if ! predicate
361
- return false
362
- elsif predicate.is_a? TrueClass
363
- return "has_#{field_name}?".to_sym
364
- end
365
-
366
- begin
367
- predicate.to_sym
368
- rescue => e
369
- # create a nested exception here
370
- raise InvalidAttributeError, "cannot coerce field predicate to a symbol for #{field_name}: #{e}"
371
- end
372
- end,
373
- clearer: lambda do|clearer, field_name|
374
- if ! clearer
375
- return false
376
- elsif clearer.is_a? TrueClass
377
- return "clear_#{field_name}!".to_sym
378
- end
85
+ subclass.define_singleton_method(:__moosex__meta) { meta }
86
+ end
379
87
 
380
- begin
381
- clearer.to_sym
382
- rescue => e
383
- # create a nested exception here
384
- raise InvalidAttributeError, "cannot coerce field clearer to a symbol for #{field_name}: #{e}"
385
- end
386
- end,
387
- handles: lambda do |handles, field_name|
388
-
389
- unless handles.is_a? Hash
390
-
391
- array_of_handles = handles
392
-
393
- unless array_of_handles.is_a? Array
394
- array_of_handles = [ array_of_handles ]
395
- end
396
-
397
- handles = array_of_handles.map do |handle|
398
-
399
- if handle == BasicObject
400
-
401
- raise InvalidAttributeError, "ops, should not use BasicObject for handles in #{field_name}"
402
-
403
- elsif handle.is_a? Class
404
-
405
- handle = handle.public_instance_methods - handle.superclass.public_instance_methods
406
-
407
- elsif handle.is_a? Module
408
-
409
- handle = handle.public_instance_methods
410
-
411
- end
412
-
413
- handle
414
-
415
- end.flatten.reduce({}) do |hash, method_name|
416
- hash.merge({ method_name => method_name })
417
- end
418
- end
419
-
420
- handles.map do |key,value|
421
- if value.is_a? Hash
422
- raise "ops! Handle should accept only one map / currying" unless value.count == 1
423
-
424
- original, currying = value.shift
425
-
426
- { key.to_sym => [original.to_sym, currying] }
427
- else
428
- { key.to_sym => value.to_sym }
429
- end
430
- end.reduce({}) do |hash,e|
431
- hash.merge(e)
432
- end
433
- end,
434
- reader: lambda do |reader, field_name|
435
- reader.to_sym
436
- end,
437
- writter: lambda do |writter, field_name|
438
- writter.to_sym
439
- end,
440
- builder: lambda do |builder, field_name|
441
- unless builder.is_a? Proc
442
- builder_method_name = builder.to_sym
443
- builder = lambda do |object|
444
- object.send(builder_method_name)
445
- end
446
- end
447
-
448
- builder
449
- end,
450
- init_arg: lambda do |init_arg, field_name|
451
- init_arg.to_sym
452
- end,
453
- trigger: lambda do |trigger, field_name|
454
- unless trigger.is_a? Proc
455
- trigger_method_name = trigger.to_sym
456
- trigger = lambda do |object, value|
457
- object.send(trigger_method_name,value)
458
- end
459
- end
460
-
461
- trigger
462
- end,
463
- coerce: lambda do |coerce, field_name|
464
- unless coerce.is_a? Proc
465
- coerce_method_name = coerce.to_sym
466
- coerce = lambda do |object|
467
- object.send(coerce_method_name)
468
- end
469
- end
470
-
471
- coerce
472
- end,
473
- weak: lambda do |weak, field_name|
474
- !! weak
475
- end,
476
- doc: lambda do |doc, field_name|
477
- doc.to_s
478
- end,
479
- override: lambda do |override, field_name|
480
- !! override
481
- end,
482
- };
483
-
484
- def initialize(a, o ,x)
485
- #o ||= {}
486
- # todo extract this to a framework, see issue #21 on facebook
487
- o = DEFAULTS.merge({
488
- reader: a,
489
- writter: a.to_s.concat("=").to_sym,
490
- builder: "build_#{a}".to_sym,
491
- init_arg: a,
492
- }).merge(o)
493
-
494
- REQUIRED.each { |field|
495
- unless o.has_key?(field)
496
- raise InvalidAttributeError, "field #{field} is required for Attribute #{a}"
497
- end
498
- }
499
- COERCE.each_pair do |field, coerce|
500
- if o.has_key? field
501
- o[field] = coerce.call(o[field], a)
502
- end
503
- end
504
- VALIDATE.each_pair do |field, validate|
505
- return if ! o.has_key? field
506
-
507
- validate.call(o[field], a)
508
- end
509
-
510
- if o[:is].eql? :ro
511
- o[:writter] = nil
512
- elsif o[:is].eql? :lazy
513
- o[:lazy] = true
514
- o[:writter] = nil
515
- end
516
-
517
- unless o[:lazy]
518
- o[:builder] = nil
519
- end
520
-
521
- if o[:weak]
522
- old_coerce = o[:coerce]
523
- o[:coerce] = lambda do |value|
524
- WeakRef.new old_coerce.call(value)
525
- end
526
- end
527
-
528
- @attr_symbol = a
529
- @is = o.delete(:is)
530
- @isa = o.delete(:isa)
531
- @default = o.delete(:default)
532
- @required = o.delete(:required)
533
- @predicate = o.delete(:predicate)
534
- @clearer = o.delete(:clearer)
535
- @handles = o.delete(:handles)
536
- @lazy = o.delete(:lazy)
537
- @reader = o.delete(:reader)
538
- @writter = o.delete(:writter)
539
- @builder = o.delete(:builder)
540
- @init_arg = o.delete(:init_arg)
541
- @trigger = o.delete(:trigger)
542
- @coerce = o.delete(:coerce)
543
- @weak = o.delete(:weak)
544
- @documentation = o.delete(:doc)
545
- @override = o.delete(:override)
546
- @methods = {}
547
-
548
- MooseX.warn "Unused attributes #{o} for attribute #{a} @ #{x} #{x.class}",caller() if ! o.empty?
549
-
550
- if @reader
551
- @methods[@reader] = generate_reader
552
- end
553
-
554
- if @writter
555
- @methods[@writter] = generate_writter
556
- end
557
- inst_variable_name = "@#{@attr_symbol}".to_sym
558
- if @predicate
559
- @methods[@predicate] = Proc.new do
560
- instance_variable_defined? inst_variable_name
561
- end
562
- end
563
-
564
- if @clearer
565
- @methods[@clearer] = Proc.new do
566
- if instance_variable_defined? inst_variable_name
567
- remove_instance_variable inst_variable_name
568
- end
569
- end
570
- end
571
-
572
- attr_symbol = @attr_symbol
573
- @handles.each_pair do | method, target_method |
574
- if target_method.is_a? Array
575
- original, currying = target_method
576
-
577
- @methods[method] = Proc.new do |*args, &proc|
578
-
579
- a1 = [ currying ]
580
-
581
- if currying.is_a?Proc
582
- a1 = currying.call()
583
- elsif currying.is_a? Array
584
- a1 = currying.map{|c| (c.is_a?(Proc)) ? c.call : c }
585
- end
586
-
587
- self.send(attr_symbol).send(original, *a1, *args, &proc)
588
- end
589
- else
590
- @methods[method] = Proc.new do |*args, &proc|
591
- self.send(attr_symbol).send(target_method, *args, &proc)
592
- end
593
- end
594
- end
595
- end
596
-
597
- def init(object, args)
598
- value = nil
599
- value_from_default = false
88
+ def class_or_module.included(other_class_or_module)
600
89
 
601
- if args.has_key? @init_arg
602
- value = args.delete(@init_arg)
603
- elsif @default
604
- value = @default.call
605
- value_from_default = true
606
- elsif @required
607
- raise InvalidAttributeError, "attr \"#{@attr_symbol}\" is required"
608
- else
609
- return
610
- end
90
+ MooseX.included(other_class_or_module)
611
91
 
612
- value = @coerce.call(value)
613
- begin
614
- @isa.call( value )
615
- rescue MooseX::Types::TypeCheckError => e
616
- raise MooseX::Types::TypeCheckError, "isa check for field #{attr_symbol}: #{e}"
617
- end
618
- unless value_from_default
619
- @trigger.call(object, value)
620
- end
621
- inst_variable_name = "@#{@attr_symbol}".to_sym
622
- object.instance_variable_set inst_variable_name, value
623
- end
92
+ other_class_or_module.__moosex__meta.load_from(self)
624
93
 
625
- private
626
- def generate_reader
627
- inst_variable_name = "@#{@attr_symbol}".to_sym
628
-
629
- builder = @builder
630
- before_get = lambda {|object| }
94
+ if other_class_or_module.is_a? Class
631
95
 
632
- if @lazy
633
- type_check = @isa
634
- coerce = @coerce
635
- trigger = @trigger
636
- before_get = lambda do |object|
637
- return if object.instance_variable_defined? inst_variable_name
96
+ other_class_or_module.__moosex__meta.load_from_klass(self)
638
97
 
639
- value = builder.call(object)
640
- value = coerce.call(value)
641
- begin
642
- type_check.call( value )
643
- rescue MooseX::Types::TypeCheckError => e
644
- raise MooseX::Types::TypeCheckError, "isa check for #{inst_variable_name} from builder: #{e}"
645
- end
98
+ self.__moosex__meta.init_klass(other_class_or_module).each_pair do |method_name, proc|
99
+ other_class_or_module.class_eval do
100
+ define_method(method_name,&proc)
101
+ end
102
+ end
646
103
 
647
- trigger.call(object, value)
648
- object.instance_variable_set(inst_variable_name, value)
649
- end
650
- end
104
+ other_class_or_module.__moosex__meta.verify_requires_for(other_class_or_module)
651
105
 
652
- Proc.new do
653
- before_get.call(self)
654
- instance_variable_get inst_variable_name
655
- end
106
+ end
656
107
  end
657
-
658
- def generate_writter
659
- writter_name = @writter
660
- inst_variable_name = "@#{@attr_symbol}".to_sym
661
- coerce = @coerce
662
- type_check = @isa
663
- trigger = @trigger
664
- Proc.new do |value|
665
- value = coerce.call(value)
666
- begin
667
- type_check.call( value )
668
- rescue MooseX::Types::TypeCheckError => e
669
- raise MooseX::Types::TypeCheckError, "isa check for #{writter_name}: #{e}"
670
- end
671
- trigger.call(self,value)
672
- instance_variable_set inst_variable_name, value
673
- end
674
- end
675
108
  end
676
109
  end