moosex 0.0.7 → 0.0.8

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: 8494a9819b7d500cafd3b8296714bd59cbcdad27
4
- data.tar.gz: 2939d832b895dd24a00a829030de65f315cb6005
3
+ metadata.gz: 762256a8cbd9378b2e80924fda5e278861f38f7e
4
+ data.tar.gz: fdbd36add8e84286e0094a907f5b24830d1d0e80
5
5
  SHA512:
6
- metadata.gz: 2510660f1124aedb3221696c4b20f4e45aaa3cf2c6ae42f2457c19d918ef45fb7e6d9afedca3b37e71d3cd3c1997e79f83f5064d4bb050a2b6943c647a8859e9
7
- data.tar.gz: d0551a59229e8bbb1bffabbfe72443d0d2e2993e3ceae24d99afdb7adbd8ee616f01ef39ef3c703eca04b07681b8e4e79caf0e70178b6e462b87eaa0a5fd3758
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moosex (0.0.7)
4
+ moosex (0.0.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
- define_method attr.attr_symbol, &g
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 "#{attr.attr_symbol}=", &s
76
+ define_method attr.writter, &s
77
77
 
78
78
  when :rwp
79
- define_method "#{attr.attr_symbol}=", &s
79
+ define_method attr.writter, &s
80
80
 
81
- private "#{attr.attr_symbol}="
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
- o = DEFAULTS.merge(o)
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? @attr_symbol
264
- value = args[ @attr_symbol ]
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? :ro
308
+ if @is.eql?(:ro) || @is.eql?(:lazy)
274
309
 
275
310
  # TODO: remove redundancy
276
311
 
277
- type_check = generate_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( setter, value )
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
- Proc.new { instance_variable_get inst_variable_name }
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 = generate_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
@@ -1,3 +1,3 @@
1
1
  module Moosex
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
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 # to run with type-check you must
367
- self.y= 0 # use the setter instad @x=
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.7
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-01 00:00:00.000000000 Z
11
+ date: 2014-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler