moosex 0.0.7 → 0.0.8
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.
- checksums.yaml +4 -4
- data/Changelog +6 -1
- data/Gemfile.lock +1 -1
- data/README.md +63 -1
- data/lib/moosex.rb +73 -22
- data/lib/moosex/version.rb +1 -1
- data/spec/moosex_spec.rb +158 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 762256a8cbd9378b2e80924fda5e278861f38f7e
|
4
|
+
data.tar.gz: fdbd36add8e84286e0094a907f5b24830d1d0e80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2215ab98afd2f0b15faa905e8de8dfc2c436814efb16bcd62c6f29474ccb7b371b96a463d45845d3e868adfb7a17df1ff2a06c7d3da1ec3e82138670fe7a8df8
|
7
|
+
data.tar.gz: 7474bb350e05b1734aec6257ec83b2a279e34839592ca48a907c6d4730c74f1fc0fe66fb4cd43cdc1d5cea5635525c08ca00013d6367d066ec7929cf7942052b
|
data/Changelog
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
0.0.8 - 2014-02-01
|
2
|
+
- should support init_arg option in attr #14
|
3
|
+
- support lazy attributes / builder #4
|
4
|
+
- support a custom name for getter / setter #9
|
5
|
+
|
1
6
|
0.0.7 - 2014-02-01
|
2
7
|
- add min version of ruby should be 2.0.x
|
3
|
-
|
8
|
+
|
4
9
|
0.0.6 - 2014-02-01
|
5
10
|
- fix bug when extends subclass, now it is safe #18
|
6
11
|
- required attr with default value will no longer throw exception #30
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -96,6 +96,34 @@ class Target
|
|
96
96
|
def method_y(a,b,c); a + b + c; end # or methods with arguments
|
97
97
|
end
|
98
98
|
|
99
|
+
class Point3D < Point
|
100
|
+
|
101
|
+
has x: { # override original attr!
|
102
|
+
is: :rw,
|
103
|
+
isa: Integer,
|
104
|
+
default: 1,
|
105
|
+
}
|
106
|
+
|
107
|
+
has z: {
|
108
|
+
is: :rw, # read-write (mandatory)
|
109
|
+
isa: Integer, # should be Integer
|
110
|
+
default: 0, # default value is 0 (constant)
|
111
|
+
}
|
112
|
+
|
113
|
+
has color: {
|
114
|
+
is: :rw, # you should specify the reader/writter
|
115
|
+
reader: :what_is_the_color_of_this_point,
|
116
|
+
writter: :set_the_color_of_this_point,
|
117
|
+
default: :red,
|
118
|
+
}
|
119
|
+
|
120
|
+
def clear
|
121
|
+
self.x= 0 # to run with type-check you must
|
122
|
+
self.y= 0 # use the setter instad @x=
|
123
|
+
self.z= 0
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
99
127
|
# now you have a generic constructor
|
100
128
|
p1 = Point.new # x and y will be 0
|
101
129
|
p2 = Point.new( x: 5 ) # y will be 0
|
@@ -223,9 +251,43 @@ end
|
|
223
251
|
```
|
224
252
|
and much more
|
225
253
|
|
254
|
+
## Lazy Attributes
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
class LazyFox
|
258
|
+
include MooseX
|
259
|
+
|
260
|
+
has something: {
|
261
|
+
is: :lazy
|
262
|
+
}
|
263
|
+
|
264
|
+
has other_thing: {
|
265
|
+
is: :rw,
|
266
|
+
lazy: true,
|
267
|
+
predicate: true,
|
268
|
+
clearer: true,
|
269
|
+
builder: :my_build_other_thing,
|
270
|
+
}
|
271
|
+
|
272
|
+
has lazy_attr_who_accepts_lambda: {
|
273
|
+
is: :lazy,
|
274
|
+
builder: lambda{ |object| object.something }
|
275
|
+
}
|
276
|
+
|
277
|
+
def build_something
|
278
|
+
1024
|
279
|
+
end
|
280
|
+
|
281
|
+
private
|
282
|
+
def my_build_other_thing
|
283
|
+
128
|
284
|
+
end
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
226
288
|
## TODO
|
227
289
|
|
228
|
-
1. Support to lazy attributes
|
290
|
+
1. Support to lazy attributes [done]
|
229
291
|
2. Support to BUILD and BUILDARGS hook
|
230
292
|
3. Support to Roles ( it is a Module on Steroids )
|
231
293
|
4. Support to after/before/around
|
data/lib/moosex.rb
CHANGED
@@ -67,18 +67,18 @@ module MooseX
|
|
67
67
|
|
68
68
|
g = attr.generate_getter
|
69
69
|
|
70
|
-
|
70
|
+
define_method attr.reader, &g
|
71
71
|
|
72
72
|
s = attr.generate_setter
|
73
73
|
|
74
74
|
case attr.is
|
75
75
|
when :rw
|
76
|
-
define_method
|
76
|
+
define_method attr.writter, &s
|
77
77
|
|
78
78
|
when :rwp
|
79
|
-
define_method
|
79
|
+
define_method attr.writter, &s
|
80
80
|
|
81
|
-
private
|
81
|
+
private attr.writter
|
82
82
|
end
|
83
83
|
|
84
84
|
__meta.add(attr)
|
@@ -88,7 +88,7 @@ module MooseX
|
|
88
88
|
|
89
89
|
class Attribute
|
90
90
|
|
91
|
-
attr_reader :attr_symbol, :is
|
91
|
+
attr_reader :attr_symbol, :is, :reader, :writter, :lazy, :builder
|
92
92
|
DEFAULTS= {
|
93
93
|
lazy: false,
|
94
94
|
clearer: false,
|
@@ -106,7 +106,6 @@ module MooseX
|
|
106
106
|
raise "invalid value for field '#{field_name}' is '#{is}', must be one of :rw, :rwp, :ro or :lazy"
|
107
107
|
end
|
108
108
|
end,
|
109
|
-
handles: lambda {|handles, field_name| true }, # TODO: add implementation
|
110
109
|
};
|
111
110
|
|
112
111
|
COERCE = {
|
@@ -199,12 +198,37 @@ module MooseX
|
|
199
198
|
end.reduce({}) do |hash,e|
|
200
199
|
hash.merge(e)
|
201
200
|
end
|
202
|
-
end,
|
201
|
+
end,
|
202
|
+
reader: lambda do |reader, field_name|
|
203
|
+
reader.to_sym
|
204
|
+
end,
|
205
|
+
writter: lambda do |writter, field_name|
|
206
|
+
writter.to_sym
|
207
|
+
end,
|
208
|
+
builder: lambda do |builder, field_name|
|
209
|
+
unless builder.is_a? Proc
|
210
|
+
builder_method_name = builder.to_sym
|
211
|
+
builder = lambda do |object|
|
212
|
+
object.send(builder_method_name)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
builder
|
217
|
+
end,
|
218
|
+
init_arg: lambda do |init_arg, field_name|
|
219
|
+
init_arg.to_sym
|
220
|
+
end,
|
203
221
|
};
|
204
222
|
|
205
223
|
def initialize(a, o)
|
206
224
|
# todo extract this to a framework, see issue #21 on facebook
|
207
|
-
|
225
|
+
|
226
|
+
o = DEFAULTS.merge({
|
227
|
+
reader: a,
|
228
|
+
writter: a.to_s.concat("=").to_sym,
|
229
|
+
builder: "build_#{a}".to_sym,
|
230
|
+
init_arg: a,
|
231
|
+
}).merge(o)
|
208
232
|
|
209
233
|
REQUIRED.each { |field|
|
210
234
|
unless o.has_key?(field)
|
@@ -220,6 +244,14 @@ module MooseX
|
|
220
244
|
return if ! o.has_key? field
|
221
245
|
|
222
246
|
validate.call(o[field], a)
|
247
|
+
end
|
248
|
+
|
249
|
+
if o[:is].eql? :lazy
|
250
|
+
o[:lazy] = true
|
251
|
+
end
|
252
|
+
|
253
|
+
unless o[:lazy]
|
254
|
+
o[:builder] = nil
|
223
255
|
end
|
224
256
|
|
225
257
|
@attr_symbol = a
|
@@ -231,12 +263,15 @@ module MooseX
|
|
231
263
|
@clearer = o[:clearer]
|
232
264
|
@handles = o[:handles]
|
233
265
|
@lazy = o[:lazy]
|
266
|
+
@reader = o[:reader]
|
267
|
+
@writter = o[:writter]
|
268
|
+
@builder = o[:builder]
|
269
|
+
@init_arg = o[:init_arg]
|
234
270
|
end
|
235
271
|
|
236
272
|
def init(object, args)
|
237
273
|
inst_variable_name = "@#{@attr_symbol}".to_sym
|
238
274
|
|
239
|
-
setter = @attr_symbol.to_s.concat("=").to_sym
|
240
275
|
value = nil
|
241
276
|
|
242
277
|
attr_symbol = @attr_symbol
|
@@ -260,8 +295,8 @@ module MooseX
|
|
260
295
|
end
|
261
296
|
end
|
262
297
|
|
263
|
-
if args.has_key? @
|
264
|
-
value = args[ @
|
298
|
+
if args.has_key? @init_arg
|
299
|
+
value = args[ @init_arg ]
|
265
300
|
elsif @default
|
266
301
|
value = @default.call
|
267
302
|
elsif @required
|
@@ -270,38 +305,54 @@ module MooseX
|
|
270
305
|
return
|
271
306
|
end
|
272
307
|
|
273
|
-
if @is.eql? :
|
308
|
+
if @is.eql?(:ro) || @is.eql?(:lazy)
|
274
309
|
|
275
310
|
# TODO: remove redundancy
|
276
311
|
|
277
|
-
type_check =
|
312
|
+
type_check = @isa
|
278
313
|
type_check.call(value)
|
314
|
+
|
279
315
|
object.instance_variable_set inst_variable_name, value
|
280
316
|
|
281
317
|
else
|
282
318
|
|
283
|
-
object.send(
|
319
|
+
object.send( @writter, value )
|
284
320
|
|
285
321
|
end
|
286
322
|
end
|
287
323
|
|
288
324
|
def generate_getter
|
289
325
|
inst_variable_name = "@#{@attr_symbol}".to_sym
|
290
|
-
|
326
|
+
|
327
|
+
builder = @builder
|
328
|
+
before_get = lambda {|object| }
|
329
|
+
|
330
|
+
if @lazy
|
331
|
+
type_check = @isa
|
332
|
+
|
333
|
+
before_get = lambda do |object|
|
334
|
+
return if object.instance_variable_defined? inst_variable_name
|
335
|
+
|
336
|
+
value = builder.call(object)
|
337
|
+
type_check.call(value)
|
338
|
+
|
339
|
+
object.instance_variable_set(inst_variable_name, value)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
Proc.new do
|
344
|
+
before_get.call(self)
|
345
|
+
instance_variable_get inst_variable_name
|
346
|
+
end
|
291
347
|
end
|
292
348
|
|
293
349
|
def generate_setter
|
294
350
|
inst_variable_name = "@#{@attr_symbol}".to_sym
|
295
|
-
type_check =
|
351
|
+
type_check = @isa
|
296
352
|
Proc.new do |value|
|
297
353
|
type_check.call(value)
|
298
354
|
instance_variable_set inst_variable_name, value
|
299
355
|
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def generate_type_check
|
303
|
-
|
304
|
-
return @isa
|
305
|
-
end
|
356
|
+
end
|
306
357
|
end
|
307
358
|
end
|
data/lib/moosex/version.rb
CHANGED
data/spec/moosex_spec.rb
CHANGED
@@ -78,6 +78,11 @@ class Foo
|
|
78
78
|
is: :rwp, # read-write-private (private setter)
|
79
79
|
required: true, # you should require in the constructor
|
80
80
|
}
|
81
|
+
|
82
|
+
has my_other_bar: {
|
83
|
+
is: :rw,
|
84
|
+
init_arg: :bar2
|
85
|
+
}
|
81
86
|
end
|
82
87
|
|
83
88
|
describe "Foo" do
|
@@ -98,6 +103,11 @@ describe "Foo" do
|
|
98
103
|
foo.bar = 1024
|
99
104
|
}.to raise_error(NoMethodError)
|
100
105
|
end
|
106
|
+
|
107
|
+
it "should be possible initialize my_other_bar by bar2" do
|
108
|
+
foo = Foo.new( bar: 1, bar2: 555)
|
109
|
+
foo.my_other_bar.should == 555
|
110
|
+
end
|
101
111
|
end
|
102
112
|
|
103
113
|
class Baz
|
@@ -362,9 +372,16 @@ class Point3D < Point
|
|
362
372
|
default: 0, # default value is 0 (constant)
|
363
373
|
}
|
364
374
|
|
375
|
+
has color: {
|
376
|
+
is: :rw, # you should specify the reader/writter
|
377
|
+
reader: :what_is_the_color_of_this_point,
|
378
|
+
writter: :set_the_color_of_this_point,
|
379
|
+
default: :red,
|
380
|
+
}
|
381
|
+
|
365
382
|
def clear
|
366
|
-
self.x= 0
|
367
|
-
self.y= 0
|
383
|
+
self.x= 0 # to run with type-check you must
|
384
|
+
self.y= 0 # use the setter instad @x=
|
368
385
|
self.z= 0
|
369
386
|
end
|
370
387
|
end
|
@@ -376,20 +393,23 @@ describe "Point3D" do
|
|
376
393
|
p.x.should == 1
|
377
394
|
p.y.should be_zero
|
378
395
|
p.z.should be_zero
|
396
|
+
p.what_is_the_color_of_this_point.should == :red
|
379
397
|
end
|
380
398
|
|
381
399
|
it "should initialize only y" do
|
382
400
|
p = Point3D.new( x: 5 )
|
383
401
|
p.x.should == 5
|
384
402
|
p.y.should be_zero
|
385
|
-
p.z.should be_zero
|
403
|
+
p.z.should be_zero
|
404
|
+
p.what_is_the_color_of_this_point.should == :red
|
386
405
|
end
|
387
406
|
|
388
407
|
it "should initialize x and y" do
|
389
|
-
p = Point3D.new( x: 5, y: 4, z: 8)
|
408
|
+
p = Point3D.new( x: 5, y: 4, z: 8, color: :yellow)
|
390
409
|
p.x.should == 5
|
391
410
|
p.y.should == 4
|
392
411
|
p.z.should == 8
|
412
|
+
p.what_is_the_color_of_this_point.should == :yellow
|
393
413
|
end
|
394
414
|
end
|
395
415
|
|
@@ -421,4 +441,138 @@ describe "Point3D" do
|
|
421
441
|
p.z.should be_zero
|
422
442
|
end
|
423
443
|
end
|
444
|
+
|
445
|
+
describe "should create the accessors names with custom names" do
|
446
|
+
it "should get/set" do
|
447
|
+
p = Point3D.new
|
448
|
+
p.what_is_the_color_of_this_point.should == :red
|
449
|
+
p.set_the_color_of_this_point(:black)
|
450
|
+
p.what_is_the_color_of_this_point.should == :black
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
class LazyFox
|
456
|
+
include MooseX
|
457
|
+
|
458
|
+
has something: {
|
459
|
+
is: :lazy
|
460
|
+
}
|
461
|
+
|
462
|
+
has other_thing: {
|
463
|
+
is: :rw,
|
464
|
+
lazy: true,
|
465
|
+
predicate: true,
|
466
|
+
clearer: true,
|
467
|
+
builder: :my_build_other_thing,
|
468
|
+
}
|
469
|
+
|
470
|
+
has lazy_attr_who_accepts_lambda: {
|
471
|
+
is: :lazy,
|
472
|
+
builder: lambda{ |object| object.something }
|
473
|
+
}
|
474
|
+
|
475
|
+
has lazy_with_default: {
|
476
|
+
is: :lazy,
|
477
|
+
default: 10,
|
478
|
+
clearer: true,
|
479
|
+
builder: lambda {|o| 1 },
|
480
|
+
}
|
481
|
+
|
482
|
+
has last_lazy_attr: {
|
483
|
+
is: :rw,
|
484
|
+
lazy: true,
|
485
|
+
}
|
486
|
+
|
487
|
+
def build_something
|
488
|
+
1024
|
489
|
+
end
|
490
|
+
|
491
|
+
private
|
492
|
+
def my_build_other_thing
|
493
|
+
128
|
494
|
+
end
|
424
495
|
end
|
496
|
+
|
497
|
+
describe "LazyFox" do
|
498
|
+
it "lazy attr should be act as a normal read only attr" do
|
499
|
+
l = LazyFox.new(something: 0)
|
500
|
+
l.something.should == 0
|
501
|
+
end
|
502
|
+
|
503
|
+
it "lazy attr should be read-only" do
|
504
|
+
l = LazyFox.new
|
505
|
+
expect{
|
506
|
+
l.something= 1
|
507
|
+
}.to raise_error(NoMethodError)
|
508
|
+
end
|
509
|
+
|
510
|
+
it "lazy: true but is :rw should act as a defered default value" do
|
511
|
+
l = LazyFox.new
|
512
|
+
l.other_thing.should == 128
|
513
|
+
l.other_thing = 9
|
514
|
+
l.other_thing.should == 9
|
515
|
+
end
|
516
|
+
|
517
|
+
it "lazy: true should not exists until necessary" do
|
518
|
+
l = LazyFox.new
|
519
|
+
l.has_other_thing?.should be_false
|
520
|
+
|
521
|
+
l.other_thing.should == 128
|
522
|
+
|
523
|
+
l.has_other_thing?.should be_true
|
524
|
+
end
|
525
|
+
|
526
|
+
it "lazy: true :rw should build again" do
|
527
|
+
l = LazyFox.new
|
528
|
+
l.other_thing.should == 128
|
529
|
+
|
530
|
+
l.has_other_thing?.should be_true
|
531
|
+
|
532
|
+
l.reset_other_thing!
|
533
|
+
|
534
|
+
l.has_other_thing?.should be_false
|
535
|
+
|
536
|
+
l.other_thing.should == 128
|
537
|
+
|
538
|
+
l.has_other_thing?.should be_true
|
539
|
+
end
|
540
|
+
|
541
|
+
it "lazy attr should call build if necessary" do
|
542
|
+
l = LazyFox.new
|
543
|
+
l.something.should == 1024
|
544
|
+
l.other_thing.should == 128
|
545
|
+
end
|
546
|
+
|
547
|
+
it "lazy attr should accept lambda" do
|
548
|
+
l = LazyFox.new
|
549
|
+
l.lazy_attr_who_accepts_lambda.should == 1024
|
550
|
+
end
|
551
|
+
|
552
|
+
it "lazy attr should accept lambda (2)" do
|
553
|
+
l = LazyFox.new(something: 2)
|
554
|
+
l.lazy_attr_who_accepts_lambda.should == 2
|
555
|
+
end
|
556
|
+
|
557
|
+
it "lazy_with_default should be initialize with default value" do
|
558
|
+
l = LazyFox.new
|
559
|
+
l.lazy_with_default.should == 10
|
560
|
+
l.reset_lazy_with_default!
|
561
|
+
l.lazy_with_default.should == 1
|
562
|
+
end
|
563
|
+
|
564
|
+
it "last_lazy_attr will raise error without a builder" do
|
565
|
+
l = LazyFox.new
|
566
|
+
expect {
|
567
|
+
l.last_lazy_attr
|
568
|
+
}.to raise_error(NoMethodError)
|
569
|
+
end
|
570
|
+
|
571
|
+
it "last_lazy_attr will not raise error with a builder" do
|
572
|
+
l = LazyFox.new
|
573
|
+
def l.build_last_lazy_attr
|
574
|
+
0
|
575
|
+
end
|
576
|
+
l.last_lazy_attr.should be_zero
|
577
|
+
end
|
578
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moosex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Peczenyj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|