moosex 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +232 -5
- data/lib/moosex.rb +113 -27
- data/lib/moosex/types.rb +225 -0
- data/lib/moosex/version.rb +2 -2
- data/moosex.gemspec +1 -1
- data/spec/complex_spec.rb +33 -0
- data/spec/hooks_spec.rb +96 -0
- data/spec/point_spec.rb +9 -4
- data/spec/types_spec.rb +477 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd8eb35f9d9028cc9f148b60f56f49ae49b2472f
|
4
|
+
data.tar.gz: 0c94cb4df401dd137d59ca3133917ddf7f195d9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1feb33f6f36589c92562a2c15a89e71a8267dab34e4742ef9b5d3743f1fb2be1828a5e653d9926fa22ec68a697731d31856845b16799d0dee70163ed20e28dc4
|
7
|
+
data.tar.gz: d58b9b922630abd5ff3160641661887d9bdde81df95afa4f413cc13cb7430b82a1b08ce15e7091251cfaddf19c658f55640436b5170fe32491190e657f4eef9f
|
data/Changelog
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# MooseX
|
2
2
|
|
3
|
-
A postmodern object DSL for Ruby [![Build Status](https://travis-ci.org/peczenyj/MooseX.png)](https://travis-ci.org/peczenyj/MooseX)
|
3
|
+
A postmodern object DSL for Ruby [![Build Status](https://travis-ci.org/peczenyj/MooseX.png)](https://travis-ci.org/peczenyj/MooseX) [![Gem Version](https://badge.fury.io/rb/moosex.png)](http://badge.fury.io/rb/moosex)
|
4
4
|
|
5
5
|
THIS MODULE IS EXPERIMENTAL YET! BE CAREFUL!
|
6
6
|
|
@@ -137,7 +137,6 @@ You can specify your own kind of type validation.
|
|
137
137
|
raise "bar should respond to to_sym method!"
|
138
138
|
end
|
139
139
|
end,
|
140
|
-
end
|
141
140
|
```
|
142
141
|
|
143
142
|
Important: if you access the attribute instance name using @attribute_name= you loose the type check feature. You need always set/get the attribute value using the acessors generated by MooseX.
|
@@ -154,6 +153,18 @@ or
|
|
154
153
|
default: lambda{ MyObject.new },
|
155
154
|
```
|
156
155
|
|
156
|
+
### required
|
157
|
+
|
158
|
+
if true, the constructor will raise error if this attribute was not present.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
required: true,
|
162
|
+
```
|
163
|
+
|
164
|
+
if this attribute has a default value, we will initialize with this value and no exception will be raised.
|
165
|
+
|
166
|
+
Optional.
|
167
|
+
|
157
168
|
### coerce
|
158
169
|
|
159
170
|
You can try to coerce the attribute value by a lambda before the type check phase. For example you can do
|
@@ -195,7 +206,9 @@ Optional.
|
|
195
206
|
You can specify one lambda or method name to be executed in each writter ( if coerce and type check does not raise any exception ). The trigger will be called in each setter and in the constructor if we do not use the default value. Useful to add a logging operation or some complex validation.
|
196
207
|
|
197
208
|
```ruby
|
198
|
-
trigger: lambda
|
209
|
+
trigger: lambda do |object, new_value|
|
210
|
+
object.logger.log "change the attribute value to #{new_value}"
|
211
|
+
end
|
199
212
|
```
|
200
213
|
or
|
201
214
|
```ruby
|
@@ -282,7 +295,7 @@ class Foo
|
|
282
295
|
is: :rw,
|
283
296
|
writter: :x=,
|
284
297
|
reader: :x,
|
285
|
-
|
298
|
+
init_arg: :x,
|
286
299
|
}
|
287
300
|
end
|
288
301
|
|
@@ -341,6 +354,220 @@ end
|
|
341
354
|
```
|
342
355
|
Optional.
|
343
356
|
|
357
|
+
## Hooks: after/before/around
|
358
|
+
|
359
|
+
Another great feature imported from Moose are the hooks after/before/around one method. You can run an arbitrary code, for example:
|
360
|
+
|
361
|
+
```ruby
|
362
|
+
class Point
|
363
|
+
include MooseX
|
364
|
+
|
365
|
+
has [:x, :y ], { is: :rw, required: true }
|
366
|
+
|
367
|
+
def clear!
|
368
|
+
self.x = 0
|
369
|
+
self.y = 0
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
class Point3D < Point
|
374
|
+
|
375
|
+
has z: { is: :rw, required: true }
|
376
|
+
|
377
|
+
after :clear! do |object|
|
378
|
+
object.z = 0
|
379
|
+
end
|
380
|
+
end
|
381
|
+
```
|
382
|
+
|
383
|
+
instead redefine the 'clear!' method in the subclass, we just add a piece of code, a lambda, and it will be executed after the normal 'clear!' method.
|
384
|
+
|
385
|
+
### after
|
386
|
+
|
387
|
+
The after hook should receive the name of the method as a Symbol and a lambda. This lambda will, in the argument list, one reference for the object (self) and the rest of the arguments. This will redefine the the original method, add the code to run after the method. The after does not affect the return value of the original method, if you need this, use the 'around' hook.
|
388
|
+
|
389
|
+
### before
|
390
|
+
|
391
|
+
The before hook should receive the name of the method as a Symbol and a lambda. This lambda will, in the argument list, one reference for the object (self) and the rest of the arguments. This will redefine the the original method, add the code to run before the method.
|
392
|
+
|
393
|
+
A good example should be logging:
|
394
|
+
|
395
|
+
```ruby
|
396
|
+
class Point
|
397
|
+
include MooseX
|
398
|
+
|
399
|
+
def my_method(x)
|
400
|
+
# do something
|
401
|
+
end
|
402
|
+
|
403
|
+
before :my_method do |object, x|
|
404
|
+
puts "#{Time.now} before my_method(#{x})"
|
405
|
+
end
|
406
|
+
after :my_method do |object, x|
|
407
|
+
puts "#{Time.now} after my_method(#{x})"
|
408
|
+
end
|
409
|
+
end
|
410
|
+
```
|
411
|
+
|
412
|
+
### around
|
413
|
+
|
414
|
+
The around hook is agressive: it will substitute the original method for a lambda. This lambda will receive the original method, a reference for the object and the argument list
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
around(:sum) do |original_method, object, a,b,c|
|
418
|
+
result = original_method.bind(object).call(a,b,c)
|
419
|
+
result + 1
|
420
|
+
end
|
421
|
+
```
|
422
|
+
|
423
|
+
it is useful to manipulate the return value if you need.
|
424
|
+
|
425
|
+
## Types
|
426
|
+
|
427
|
+
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:
|
428
|
+
|
429
|
+
### isAny
|
430
|
+
|
431
|
+
will accept any type. Useful to combine with other types.
|
432
|
+
|
433
|
+
```ruby
|
434
|
+
has x: { is: :rw, isa: isAny }
|
435
|
+
```
|
436
|
+
|
437
|
+
### isConstant
|
438
|
+
|
439
|
+
will verify using :=== if the value is equal to some contant
|
440
|
+
|
441
|
+
```ruby
|
442
|
+
has x: { is: :rw, isa: isConstant(1) }
|
443
|
+
```
|
444
|
+
|
445
|
+
### isType, isInstanceOf and isConsumerOf
|
446
|
+
|
447
|
+
will verify the type using is_a? method. should receive a Class. isInstanceOf is an alias, to be used with Classes and isConsumerOf is for Modules.
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
has x: { is: :rw, isa: isConsumerOf(Enumerable) }
|
451
|
+
```
|
452
|
+
|
453
|
+
### hasMethods
|
454
|
+
|
455
|
+
will verify if the value respond_to? for one or more methods.
|
456
|
+
|
457
|
+
```ruby
|
458
|
+
has x: { is: :rw, isa: hasMethods(:to_s) }
|
459
|
+
```
|
460
|
+
### isEnum
|
461
|
+
|
462
|
+
verify if the value is part of one enumeration of constants.
|
463
|
+
|
464
|
+
```ruby
|
465
|
+
has x: { is: :rw, isa: isEnum(:black, :white, :red, :green, :yellow) }
|
466
|
+
```
|
467
|
+
|
468
|
+
### isMaybe(type)
|
469
|
+
|
470
|
+
verify if the value isa type or is nil. You can combine with other types.
|
471
|
+
|
472
|
+
```ruby
|
473
|
+
has x: { is: :rw, isa: isMaybe(Integer) } # accepts 1,2,3... or nil
|
474
|
+
```
|
475
|
+
|
476
|
+
### isNot(type)
|
477
|
+
|
478
|
+
will revert the type check. Useful to combine with other types
|
479
|
+
|
480
|
+
```ruby
|
481
|
+
has x: {
|
482
|
+
is: :rw, # x will accept any values EXCEPT :black, :white...
|
483
|
+
isa: isNot(isEnum(:black, :white, :red, :green, :yellow))
|
484
|
+
}
|
485
|
+
```
|
486
|
+
|
487
|
+
### isArray(type)
|
488
|
+
|
489
|
+
Will verify if the value is an Array. Can receive one extra type, and we will verify each element inside the array againt this type, or Any if we not specify the type.
|
490
|
+
|
491
|
+
```ruby
|
492
|
+
has x: {
|
493
|
+
is: :rw,
|
494
|
+
isa: isArray() # will accept any array
|
495
|
+
}
|
496
|
+
has y: {
|
497
|
+
is: :rw, # this is a more complex type
|
498
|
+
isa: isArray(isArray(isMaybe(Integer)))
|
499
|
+
}
|
500
|
+
```
|
501
|
+
|
502
|
+
### isHash(type=>type)
|
503
|
+
|
504
|
+
similar to isArray. if you do not specify a pair of types, it will check only if the value is_a? Hash. Otherwise we will verify each pair key/value.
|
505
|
+
|
506
|
+
```ruby
|
507
|
+
has x: {
|
508
|
+
is: :rw,
|
509
|
+
isa: isHash() # will accept any Hash
|
510
|
+
}
|
511
|
+
has y: {
|
512
|
+
is: :rw, # this is a more complex type
|
513
|
+
isa: isHash(Integer => isArray(isMaybe(Integer)))
|
514
|
+
}
|
515
|
+
```
|
516
|
+
|
517
|
+
## isSet(type)
|
518
|
+
|
519
|
+
similar to isSet. the difference is: it will raise one exception if there are non unique elements in this array.
|
520
|
+
|
521
|
+
```ruby
|
522
|
+
has x: {
|
523
|
+
is: :rw,
|
524
|
+
isa: isSet(Integer) # will accept [1,2,3] but not [1,1,1]
|
525
|
+
}
|
526
|
+
```
|
527
|
+
|
528
|
+
## isTuple(types)
|
529
|
+
|
530
|
+
similar to isArray, Tuples are Arrays with fixed size. We will verify the type of each element.
|
531
|
+
|
532
|
+
For example, to specify one tuple with three elements, the first is Integer, the second is a Symbol and the las should be a String or nil:
|
533
|
+
|
534
|
+
```ruby
|
535
|
+
has x: {
|
536
|
+
is: :rw,
|
537
|
+
isa: isTuple(Integer, Symbol, isMaybe(String))
|
538
|
+
}
|
539
|
+
```
|
540
|
+
|
541
|
+
### isAllOf(types)
|
542
|
+
|
543
|
+
will combine all types and will fail if one of the condition fails.
|
544
|
+
|
545
|
+
```ruby
|
546
|
+
has x: {
|
547
|
+
is: :rw,
|
548
|
+
isa: isAllOf(
|
549
|
+
hasMethods(:foo, :bar), # x should has foo and bar methods
|
550
|
+
isConsumerOf(Enumerable), # AND should be an Enumerable
|
551
|
+
isNot(SomeForbiddenClass), # AND and should not be an SomeForbiddenClass
|
552
|
+
)
|
553
|
+
}
|
554
|
+
```
|
555
|
+
|
556
|
+
### isAnyOf(types)
|
557
|
+
|
558
|
+
will combine all types and will fail if all of the condition fails.
|
559
|
+
|
560
|
+
```ruby
|
561
|
+
has x: {
|
562
|
+
is: :rw,
|
563
|
+
isa: isAnyOf(
|
564
|
+
hasMethods(:foo, :bar), # x should has foo and bar methods
|
565
|
+
isEnum(1,2,3,4), # OR be 1,2,3 or 4
|
566
|
+
isHash(isAny => Integer) # OR be an Hash of any type => Integers
|
567
|
+
)
|
568
|
+
}
|
569
|
+
```
|
570
|
+
|
344
571
|
## BUILD
|
345
572
|
|
346
573
|
If you need run some code after the creation of the object (like some extra validation), you should override the BUILD method.
|
@@ -362,7 +589,7 @@ end
|
|
362
589
|
|
363
590
|
b1 = BuildExample.new(x: 1, y: 2) # will create the object
|
364
591
|
b2 = BuildExample.new(x: 1, y: 1) # will raise the exception!
|
365
|
-
```
|
592
|
+
```
|
366
593
|
|
367
594
|
### BUILDARGS
|
368
595
|
|
data/lib/moosex.rb
CHANGED
@@ -6,9 +6,10 @@
|
|
6
6
|
# License:: MIT
|
7
7
|
#
|
8
8
|
require "moosex/version"
|
9
|
+
require "moosex/types"
|
9
10
|
|
10
11
|
module MooseX
|
11
|
-
|
12
|
+
|
12
13
|
def MooseX.included(c)
|
13
14
|
|
14
15
|
c.extend(MooseX::Core)
|
@@ -38,7 +39,7 @@ module MooseX
|
|
38
39
|
subclass.class_exec do
|
39
40
|
old_meta = subclass.__meta
|
40
41
|
|
41
|
-
meta = MooseX::Meta.new(old_meta
|
42
|
+
meta = MooseX::Meta.new(old_meta)
|
42
43
|
|
43
44
|
define_singleton_method(:__meta) { meta }
|
44
45
|
end
|
@@ -47,22 +48,78 @@ module MooseX
|
|
47
48
|
end
|
48
49
|
|
49
50
|
class Meta
|
50
|
-
attr_reader :attrs
|
51
|
-
|
52
|
-
|
51
|
+
attr_reader :attrs, :after, :before, :around
|
52
|
+
|
53
|
+
def initialize(old_meta=nil)
|
54
|
+
@attrs = []
|
55
|
+
@after = Hash.new {|hash, key| hash[key] = []}
|
56
|
+
@before= Hash.new {|hash, key| hash[key] = []}
|
57
|
+
@around= Hash.new {|hash, key| hash[key] = []}
|
58
|
+
|
59
|
+
if old_meta
|
60
|
+
@attrs = old_meta.attrs.map{|att| att.clone }
|
61
|
+
@after.merge! old_meta.after.clone
|
62
|
+
@before.merge! old_meta.before.clone
|
63
|
+
@around.merge! old_meta.around.clone
|
64
|
+
end
|
53
65
|
end
|
54
66
|
|
55
67
|
def add(attr)
|
56
68
|
@attrs << attr
|
57
69
|
end
|
70
|
+
|
71
|
+
def add_after(method, block)
|
72
|
+
@after[method] << MooseX::Hook::After.new(method, block)
|
73
|
+
end
|
58
74
|
|
75
|
+
def add_before(method, block)
|
76
|
+
@before[method] << MooseX::Hook::Before.new(method, block)
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_around(method, block)
|
80
|
+
@around[method] << MooseX::Hook::Around.new(method, block)
|
81
|
+
end
|
82
|
+
|
59
83
|
def init(object, args)
|
60
84
|
@attrs.each{ |attr| attr.init(object, args) }
|
61
85
|
end
|
62
86
|
end
|
63
87
|
|
64
88
|
module Core
|
65
|
-
|
89
|
+
def after(method_name, &block)
|
90
|
+
method = instance_method method_name
|
91
|
+
|
92
|
+
define_method method_name do |*args|
|
93
|
+
result = method.bind(self).call(*args)
|
94
|
+
block.call(self,*args)
|
95
|
+
result
|
96
|
+
end
|
97
|
+
|
98
|
+
__meta.add_after(method_name, block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def before(method_name, &block)
|
102
|
+
method = instance_method method_name
|
103
|
+
|
104
|
+
define_method method_name do |*args|
|
105
|
+
block.call(self,*args)
|
106
|
+
method.bind(self).call(*args)
|
107
|
+
end
|
108
|
+
|
109
|
+
__meta.add_before(method_name, block)
|
110
|
+
end
|
111
|
+
|
112
|
+
def around(method_name, &block)
|
113
|
+
method = instance_method method_name
|
114
|
+
|
115
|
+
define_method method_name do |*args|
|
116
|
+
|
117
|
+
block.call(method, self,*args)
|
118
|
+
|
119
|
+
end
|
120
|
+
__meta.add_around(method, block)
|
121
|
+
end
|
122
|
+
|
66
123
|
def has(attr_name, attr_options = {})
|
67
124
|
if attr_name.is_a? Array
|
68
125
|
attr_name.each do |attr|
|
@@ -92,7 +149,31 @@ module MooseX
|
|
92
149
|
end
|
93
150
|
end
|
94
151
|
|
152
|
+
module Hook
|
153
|
+
class Base
|
154
|
+
attr_reader :method, :block
|
155
|
+
def initialize(method, block)
|
156
|
+
@method= method
|
157
|
+
@block = block
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class After < Base
|
162
|
+
end
|
163
|
+
|
164
|
+
class Before < Base
|
165
|
+
end
|
166
|
+
|
167
|
+
class Around < Base
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class InvalidAttributeError < TypeError
|
172
|
+
|
173
|
+
end
|
174
|
+
|
95
175
|
class Attribute
|
176
|
+
include MooseX::Types
|
96
177
|
|
97
178
|
attr_reader :attr_symbol, :is, :reader, :writter, :lazy, :builder, :methods
|
98
179
|
DEFAULTS= {
|
@@ -100,7 +181,7 @@ module MooseX
|
|
100
181
|
clearer: false,
|
101
182
|
required: false,
|
102
183
|
predicate: false,
|
103
|
-
isa:
|
184
|
+
isa: isAny,
|
104
185
|
handles: {},
|
105
186
|
trigger: lambda {|object,value|}, # TODO: implement
|
106
187
|
coerce: lambda {|object| object}, # TODO: implement
|
@@ -111,7 +192,7 @@ module MooseX
|
|
111
192
|
VALIDATE = {
|
112
193
|
is: lambda do |is, field_name|
|
113
194
|
unless [:rw, :rwp, :ro, :lazy, :private].include?(is)
|
114
|
-
raise "invalid value for field '#{field_name}' is '#{is}', must be one of :private, :rw, :rwp, :ro or :lazy"
|
195
|
+
raise InvalidAttributeError, "invalid value for field '#{field_name}' is '#{is}', must be one of :private, :rw, :rwp, :ro or :lazy"
|
115
196
|
end
|
116
197
|
end,
|
117
198
|
};
|
@@ -121,13 +202,7 @@ module MooseX
|
|
121
202
|
is.to_sym
|
122
203
|
end,
|
123
204
|
isa: lambda do |isa, field_name|
|
124
|
-
|
125
|
-
|
126
|
-
return lambda do |new_value|
|
127
|
-
unless new_value.is_a?(isa)
|
128
|
-
raise "isa check for \"#{field_name}\" failed: is not instance of #{isa}!"
|
129
|
-
end
|
130
|
-
end
|
205
|
+
isType(isa)
|
131
206
|
end,
|
132
207
|
default: lambda do |default, field_name|
|
133
208
|
return default if default.is_a? Proc
|
@@ -151,7 +226,7 @@ module MooseX
|
|
151
226
|
predicate.to_sym
|
152
227
|
rescue => e
|
153
228
|
# create a nested exception here
|
154
|
-
raise "cannot coerce field predicate to a symbol for #{field_name}: #{e}"
|
229
|
+
raise InvalidAttributeError, "cannot coerce field predicate to a symbol for #{field_name}: #{e}"
|
155
230
|
end
|
156
231
|
end,
|
157
232
|
clearer: lambda do|clearer, field_name|
|
@@ -165,7 +240,7 @@ module MooseX
|
|
165
240
|
clearer.to_sym
|
166
241
|
rescue => e
|
167
242
|
# create a nested exception here
|
168
|
-
raise "cannot coerce field clearer to a symbol for #{field_name}: #{e}"
|
243
|
+
raise InvalidAttributeError, "cannot coerce field clearer to a symbol for #{field_name}: #{e}"
|
169
244
|
end
|
170
245
|
end,
|
171
246
|
handles: lambda do |handles, field_name|
|
@@ -182,7 +257,7 @@ module MooseX
|
|
182
257
|
|
183
258
|
if handle == BasicObject
|
184
259
|
|
185
|
-
raise "ops, should not use BasicObject for handles in #{field_name}"
|
260
|
+
raise InvalidAttributeError, "ops, should not use BasicObject for handles in #{field_name}"
|
186
261
|
|
187
262
|
elsif handle.is_a? Class
|
188
263
|
|
@@ -260,7 +335,7 @@ module MooseX
|
|
260
335
|
|
261
336
|
REQUIRED.each { |field|
|
262
337
|
unless o.has_key?(field)
|
263
|
-
raise "field #{field} is required for Attribute #{a}"
|
338
|
+
raise InvalidAttributeError, "field #{field} is required for Attribute #{a}"
|
264
339
|
end
|
265
340
|
}
|
266
341
|
COERCE.each_pair do |field, coerce|
|
@@ -342,19 +417,20 @@ module MooseX
|
|
342
417
|
value = @default.call
|
343
418
|
value_from_default = true
|
344
419
|
elsif @required
|
345
|
-
raise "attr \"#{@attr_symbol}\" is required"
|
420
|
+
raise InvalidAttributeError, "attr \"#{@attr_symbol}\" is required"
|
346
421
|
else
|
347
422
|
return
|
348
423
|
end
|
349
|
-
|
350
|
-
|
351
|
-
value = @coerce.call(value)
|
352
424
|
|
353
|
-
@
|
425
|
+
value = @coerce.call(value)
|
426
|
+
begin
|
427
|
+
@isa.call( value )
|
428
|
+
rescue MooseX::Types::TypeCheckError => e
|
429
|
+
raise MooseX::Types::TypeCheckError, "isa check for field #{attr_symbol}: #{e}"
|
430
|
+
end
|
354
431
|
unless value_from_default
|
355
432
|
@trigger.call(object, value)
|
356
433
|
end
|
357
|
-
|
358
434
|
inst_variable_name = "@#{@attr_symbol}".to_sym
|
359
435
|
object.instance_variable_set inst_variable_name, value
|
360
436
|
end
|
@@ -375,7 +451,12 @@ module MooseX
|
|
375
451
|
|
376
452
|
value = builder.call(object)
|
377
453
|
value = coerce.call(value)
|
378
|
-
|
454
|
+
begin
|
455
|
+
type_check.call( value )
|
456
|
+
rescue MooseX::Types::TypeCheckError => e
|
457
|
+
raise MooseX::Types::TypeCheckError, "isa check for #{inst_variable_name} from builder: #{e}"
|
458
|
+
end
|
459
|
+
|
379
460
|
trigger.call(object, value)
|
380
461
|
object.instance_variable_set(inst_variable_name, value)
|
381
462
|
end
|
@@ -388,13 +469,18 @@ module MooseX
|
|
388
469
|
end
|
389
470
|
|
390
471
|
def generate_writter
|
472
|
+
writter_name = @writter
|
391
473
|
inst_variable_name = "@#{@attr_symbol}".to_sym
|
392
474
|
coerce = @coerce
|
393
475
|
type_check = @isa
|
394
476
|
trigger = @trigger
|
395
477
|
Proc.new do |value|
|
396
478
|
value = coerce.call(value)
|
397
|
-
|
479
|
+
begin
|
480
|
+
type_check.call( value )
|
481
|
+
rescue MooseX::Types::TypeCheckError => e
|
482
|
+
raise MooseX::Types::TypeCheckError, "isa check for #{writter_name}: #{e}"
|
483
|
+
end
|
398
484
|
trigger.call(self,value)
|
399
485
|
instance_variable_set inst_variable_name, value
|
400
486
|
end
|