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 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