moosex 0.0.11 → 0.0.12

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: fd8eb35f9d9028cc9f148b60f56f49ae49b2472f
4
- data.tar.gz: 0c94cb4df401dd137d59ca3133917ddf7f195d9d
3
+ metadata.gz: 145aae5f2007ffa2f565296a4a256b27c32d5baa
4
+ data.tar.gz: e454cd3f240e2b47c53446bf14b44fd94aaab26e
5
5
  SHA512:
6
- metadata.gz: 1feb33f6f36589c92562a2c15a89e71a8267dab34e4742ef9b5d3743f1fb2be1828a5e653d9926fa22ec68a697731d31856845b16799d0dee70163ed20e28dc4
7
- data.tar.gz: d58b9b922630abd5ff3160641661887d9bdde81df95afa4f413cc13cb7430b82a1b08ce15e7091251cfaddf19c658f55640436b5170fe32491190e657f4eef9f
6
+ metadata.gz: 0f8761c2e4f9fbb9458f4bc7b4dc5db5f5dc1e1efa08b3d51d58da8595ec232178630afeb8909fb6b6252dabb287772e367dbc7eb2bad4c14ac38b1dc64e6094
7
+ data.tar.gz: b613aa258cc7a06e7f0f44ea7f00bfdcb8aff52bd122c512f330e4f025dcf83d61a875395158e9162dd4a88355e14d9861106c904e0bb86b42f741e1fa6a1af8
@@ -0,0 +1 @@
1
+ repo_token: CROa4WDRvgcQjh5zATUpjPRURmXEgATMt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/Changelog CHANGED
@@ -1,14 +1,18 @@
1
+ 0.0.12 - 2013-02-05
2
+ - basic support override attributes #19
3
+ - basic support to roles #17
4
+
1
5
  0.0.11 - 2013-02-04
2
6
  - basic support to after/before/around #12
3
7
  - improve exception #15
4
8
  - improve type system via MooseX::Types #16
5
9
 
6
10
  0.0.10 - 2014-02-03
7
- - improve readme #2014-02-01
8
- - BUILDARGS should accept different signatures #36
9
- - clearer create by default clear_#{attr_name}! public method
10
- - add attr :private #35
11
- - methods predicate, clearer and handles are no longer singleton methods #34
11
+ - improve readme
12
+ - BUILDARGS should accept different signatures #36
13
+ - clearer create by default clear_#{attr_name}! public method
14
+ - add attr :private #35
15
+ - methods predicate, clearer and handles are no longer singleton methods #34
12
16
 
13
17
  0.0.9 - 2014-02-02
14
18
  - support to BUILD and BUILDARGS #5 and #6
@@ -24,9 +28,9 @@
24
28
  - add min version of ruby should be 2.0.x
25
29
 
26
30
  0.0.6 - 2014-02-01
27
- - fix bug when extends subclass, now it is safe #18
28
- - required attr with default value will no longer throw exception #30
29
- - supports handles for: single method, array, Class or Module #27
31
+ - fix bug when extends subclass, now it is safe #18
32
+ - required attr with default value will no longer throw exception #30
33
+ - supports handles for: single method, array, Class or Module #27
30
34
 
31
35
  0.0.5 - 2014-01-31
32
36
  - should support handles #13 (partial)
@@ -1,12 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moosex (0.0.11)
4
+ moosex (0.0.12)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  diff-lcs (1.2.5)
10
+ docile (1.1.3)
11
+ multi_json (1.8.4)
10
12
  rake (10.1.1)
11
13
  rspec (2.14.1)
12
14
  rspec-core (~> 2.14.0)
@@ -16,6 +18,11 @@ GEM
16
18
  rspec-expectations (2.14.5)
17
19
  diff-lcs (>= 1.1.3, < 2.0)
18
20
  rspec-mocks (2.14.5)
21
+ simplecov (0.8.2)
22
+ docile (~> 1.1.0)
23
+ multi_json
24
+ simplecov-html (~> 0.8.0)
25
+ simplecov-html (0.8.0)
19
26
 
20
27
  PLATFORMS
21
28
  ruby
@@ -25,3 +32,4 @@ DEPENDENCIES
25
32
  moosex!
26
33
  rake
27
34
  rspec
35
+ simplecov
data/README.md CHANGED
@@ -382,6 +382,10 @@ end
382
382
 
383
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
384
 
385
+ Each after/before/around will **redefine** the original method in order. If you want override the method in some subclass, you will loose all hooks. The best way to preserve all hooks is using after/before/around to modify the behavior if possible.
386
+
387
+ **IMPORTANT** This behavior is temporary, there is an issue for this [here](https://github.com/peczenyj/MooseX/issues/41 "issue in github").
388
+
385
389
  ### after
386
390
 
387
391
  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.
@@ -422,15 +426,19 @@ The around hook is agressive: it will substitute the original method for a lambd
422
426
 
423
427
  it is useful to manipulate the return value if you need.
424
428
 
425
- ## Types
429
+ ## MooseX::Types
426
430
 
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:
431
+ 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
432
 
429
433
  ### isAny
430
434
 
431
435
  will accept any type. Useful to combine with other types.
432
436
 
433
437
  ```ruby
438
+ class Example
439
+ include MooseX
440
+ include MooseX::Types
441
+
434
442
  has x: { is: :rw, isa: isAny }
435
443
  ```
436
444
 
@@ -568,9 +576,60 @@ will combine all types and will fail if all of the condition fails.
568
576
  }
569
577
  ```
570
578
 
579
+ ## Roles
580
+
581
+ Roles are Modules with steroids. If you include the MooseX module in another module, this module became a "Role", capable of store attributes to be reuse in other MooseX classes. For example:
582
+
583
+ ```ruby
584
+ require 'moosex'
585
+
586
+ module Eq
587
+ include MooseX.disable_warnings() # or enable_warningss (default)
588
+
589
+ requires :equal
590
+
591
+ def no_equal(other)
592
+ ! self.equal(other)
593
+ end
594
+ end
595
+
596
+ module Valuable
597
+ include MooseX
598
+
599
+ has value: { is: :ro, required: true }
600
+ end
601
+
602
+ class Currency
603
+ include Valuable
604
+ include Eq # will warn unless disable_warnings was called.
605
+ # to avoid warnings, you should include after
606
+ # define all required modules,
607
+
608
+ def equal(other)
609
+ self.value == other.value
610
+ end
611
+
612
+ # include Eq # warning 'safe' include, after equal declaration
613
+ end
614
+
615
+ c1 = ComplexRole::Currency.new( value: 12 )
616
+ c2 = ComplexRole::Currency.new( value: 12 )
617
+
618
+ c1.equal(c2) # true, they have the same value
619
+ c1.no_equal(c2) # will return false
620
+ ```
621
+
622
+ Roles can support has to describe attributes, and you can reuse code easily. You can also use after/before/around only in methods defined/imported in that Module.
623
+
624
+ For example, we can add a 'after' block for no_equal inside Eq, but not for equal - this limitation will be fixed soon (see issue #41 @ github).
625
+
626
+ ### requires
627
+
628
+ You can also mark one or more methods as 'required'. When you do this, we will raise one exception if you try to create a new instance and the class does not implement it. It is a safe way to create interfaces or abstract classes. It uses respond_to? to verify.
629
+
571
630
  ## BUILD
572
631
 
573
- If you need run some code after the creation of the object (like some extra validation), you should override the BUILD method.
632
+ If you need run some code after the creation of the object (like some extra validation), you should implement the BUILD method.
574
633
 
575
634
  ```ruby
576
635
  class BuildExample
@@ -9,30 +9,56 @@ require "moosex/version"
9
9
  require "moosex/types"
10
10
 
11
11
  module MooseX
12
+ $MOOSEX_DEBUG = true
13
+
14
+ def MooseX.enable_warnings()
15
+ $MOOSEX_DEBUG = false
16
+ MooseX
17
+ end
18
+
19
+ def MooseX.disable_warnings()
20
+ $MOOSEX_DEBUG = false
21
+ MooseX
22
+ end
23
+
24
+ class RequiredMethodNotFoundError < NameError
25
+ end
12
26
 
13
27
  def MooseX.included(c)
14
-
28
+
15
29
  c.extend(MooseX::Core)
16
-
17
- c.class_exec do
18
- meta = MooseX::Meta.new
30
+
31
+ def c.included(x)
32
+ MooseX.included(x)
33
+ x.__meta.load_from(self.__meta)
34
+
35
+ return unless x.is_a? Class
19
36
 
20
- define_singleton_method(:__meta) { meta }
37
+ x.__meta.requires.each do |method|
38
+ unless x.public_instance_methods.include? method
39
+ warn "[MooseX] you must implement method '#{method}' in #{x} #{x.class}: required" if $MOOSEX_DEBUG
40
+ end
41
+ end
21
42
  end
22
43
 
44
+ meta = MooseX::Meta.new
45
+
46
+ unless c.respond_to? :__meta
47
+ c.class_exec do
48
+ define_singleton_method(:__meta) { meta }
49
+ end
50
+ end
51
+
23
52
  def initialize(*args)
24
- args = BUILDARGS(*args)
53
+ if self.respond_to? :BUILDARGS
54
+ args = self.BUILDARGS(*args)
55
+ else
56
+ args = args[0]
57
+ end
25
58
 
26
59
  self.class.__meta().init(self, args || {})
27
60
 
28
- BUILD()
29
- end
30
-
31
- def BUILDARGS(*args)
32
- args[0]
33
- end
34
-
35
- def BUILD
61
+ self.BUILD() if self.respond_to? :BUILD
36
62
  end
37
63
 
38
64
  def c.inherited(subclass)
@@ -48,40 +74,45 @@ module MooseX
48
74
  end
49
75
 
50
76
  class Meta
51
- attr_reader :attrs, :after, :before, :around
77
+ attr_reader :attrs, :requires
52
78
 
53
79
  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
-
80
+ @attrs = {}
81
+ @requires = []
59
82
  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
83
+ old_meta.attrs.each_pair do |key, value|
84
+ @attrs[key] = value.clone
85
+ end
86
+ @requires = old_meta.requires.clone
64
87
  end
65
88
  end
66
-
67
- def add(attr)
68
- @attrs << attr
69
- end
70
89
 
71
- def add_after(method, block)
72
- @after[method] << MooseX::Hook::After.new(method, block)
90
+ def load_from(other_meta)
91
+ other_meta.attrs.each_pair do |key, value|
92
+ @attrs[key] = value.clone
93
+ end
94
+ @requires += other_meta.requires
73
95
  end
74
96
 
75
- def add_before(method, block)
76
- @before[method] << MooseX::Hook::Before.new(method, block)
97
+ def add(attr)
98
+ @attrs[attr.attr_symbol] = attr
77
99
  end
78
100
 
79
- def add_around(method, block)
80
- @around[method] << MooseX::Hook::Around.new(method, block)
101
+ def add_requires(method)
102
+ @requires << method
81
103
  end
82
104
 
83
105
  def init(object, args)
84
- @attrs.each{ |attr| attr.init(object, args) }
106
+ @attrs.each_pair{ |symbol, attr| attr.init(object, args) }
107
+
108
+ warn "[MooseX] unused attributes #{args} for #{object.class}" if $MOOSEX_DEBUG && ! args.empty?
109
+
110
+ @requires.each do |method|
111
+ unless object.respond_to? method
112
+ raise RequiredMethodNotFoundError,
113
+ "you must implement method '#{method}' in #{object.class}: required"
114
+ end
115
+ end
85
116
  end
86
117
  end
87
118
 
@@ -95,7 +126,7 @@ module MooseX
95
126
  result
96
127
  end
97
128
 
98
- __meta.add_after(method_name, block)
129
+ # __meta.add_after(method_name, block)
99
130
  end
100
131
 
101
132
  def before(method_name, &block)
@@ -106,7 +137,7 @@ module MooseX
106
137
  method.bind(self).call(*args)
107
138
  end
108
139
 
109
- __meta.add_before(method_name, block)
140
+ # __meta.add_before(method_name, block)
110
141
  end
111
142
 
112
143
  def around(method_name, &block)
@@ -117,7 +148,14 @@ module MooseX
117
148
  block.call(method, self,*args)
118
149
 
119
150
  end
120
- __meta.add_around(method, block)
151
+ # __meta.add_around(method, block)
152
+ end
153
+
154
+ def requires(*methods)
155
+
156
+ methods.each do |method_name|
157
+ __meta.add_requires(method_name)
158
+ end
121
159
  end
122
160
 
123
161
  def has(attr_name, attr_options = {})
@@ -131,7 +169,7 @@ module MooseX
131
169
  end
132
170
  else
133
171
 
134
- attr = MooseX::Attribute.new(attr_name, attr_options)
172
+ attr = MooseX::Attribute.new(attr_name, attr_options, self)
135
173
 
136
174
  attr.methods.each_pair do |method, proc|
137
175
  define_method method, &proc
@@ -149,25 +187,6 @@ module MooseX
149
187
  end
150
188
  end
151
189
 
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
190
  class InvalidAttributeError < TypeError
172
191
 
173
192
  end
@@ -323,7 +342,7 @@ module MooseX
323
342
  end,
324
343
  };
325
344
 
326
- def initialize(a, o)
345
+ def initialize(a, o, x)
327
346
  #o ||= {}
328
347
  # todo extract this to a framework, see issue #21 on facebook
329
348
  o = DEFAULTS.merge({
@@ -361,22 +380,24 @@ module MooseX
361
380
  end
362
381
 
363
382
  @attr_symbol = a
364
- @is = o[:is]
365
- @isa = o[:isa]
366
- @default = o[:default]
367
- @required = o[:required]
368
- @predicate = o[:predicate]
369
- @clearer = o[:clearer]
370
- @handles = o[:handles]
371
- @lazy = o[:lazy]
372
- @reader = o[:reader]
373
- @writter = o[:writter]
374
- @builder = o[:builder]
375
- @init_arg = o[:init_arg]
376
- @trigger = o[:trigger]
377
- @coerce = o[:coerce]
383
+ @is = o.delete(:is)
384
+ @isa = o.delete(:isa)
385
+ @default = o.delete(:default)
386
+ @required = o.delete(:required)
387
+ @predicate = o.delete(:predicate)
388
+ @clearer = o.delete(:clearer)
389
+ @handles = o.delete(:handles)
390
+ @lazy = o.delete(:lazy)
391
+ @reader = o.delete(:reader)
392
+ @writter = o.delete(:writter)
393
+ @builder = o.delete(:builder)
394
+ @init_arg = o.delete(:init_arg)
395
+ @trigger = o.delete(:trigger)
396
+ @coerce = o.delete(:coerce)
378
397
  @methods = {}
379
398
 
399
+ warn "[MooseX] unused attributes #{o} for attribute #{a} @ #{x} #{x.class}" if $MOOSEX_DEBUG && ! o.empty?
400
+
380
401
  if @reader
381
402
  @methods[@reader] = generate_reader
382
403
  end
@@ -412,7 +433,7 @@ module MooseX
412
433
  value_from_default = false
413
434
 
414
435
  if args.has_key? @init_arg
415
- value = args[ @init_arg ]
436
+ value = args.delete(@init_arg)
416
437
  elsif @default
417
438
  value = @default.call
418
439
  value_from_default = true
@@ -1,3 +1,3 @@
1
1
  module MooseX
2
- VERSION = "0.0.11"
2
+ VERSION = "0.0.12"
3
3
  end
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.5"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "simplecov"
26
27
  end
@@ -0,0 +1,63 @@
1
+ require 'moosex'
2
+
3
+
4
+ module Eq
5
+ include MooseX.disable_warnings()
6
+
7
+ requires :equal
8
+
9
+ def no_equal(other)
10
+ ! self.equal(other)
11
+ end
12
+ end
13
+
14
+ module Valuable
15
+ include MooseX
16
+
17
+ has value: { is: :ro, requires: true }
18
+ end
19
+
20
+ class Currency
21
+ include Valuable
22
+ include Eq # will warn unless disable_warnings was called.
23
+ # to avoid warnings, you should include after
24
+ # define all required modules,
25
+
26
+ def equal(other)
27
+ self.value == other.value
28
+ end
29
+
30
+ # include Eq # warning safe include
31
+ end
32
+
33
+ class Comparator
34
+ include MooseX
35
+
36
+ has compare_to: {
37
+ is: :ro,
38
+ isa: Eq,
39
+ handles: Eq,
40
+ }
41
+ end
42
+
43
+ module Wrapper
44
+ include Eq
45
+ end
46
+
47
+ class WrongClass
48
+ include Wrapper
49
+
50
+ has one: { is: :rw }
51
+ end
52
+
53
+ c1 = Currency.new( value: 12 )
54
+ c2 = Currency.new( value: 12 )
55
+ c3 = Currency.new( value: 24 )
56
+
57
+ c1.equal(c2) # true
58
+ c1.equal(c3) # false
59
+
60
+ Comparator.new(compare_to: c1).no_equal(c2) # false
61
+ Comparator.new(compare_to: c1).no_equal(c3) # true
62
+
63
+ WrongClass.new(one: 1, two: 2) # will raise exception
@@ -0,0 +1,174 @@
1
+ require 'moosex'
2
+
3
+ module RoleTest
4
+ module Name
5
+ include MooseX
6
+
7
+ has name: { is: :rw , required: true }
8
+ end
9
+
10
+ module Address
11
+ include MooseX
12
+
13
+ has address: { is: :rw , required: true }
14
+ end
15
+
16
+ class Person
17
+ include Name
18
+ include Address
19
+
20
+ has age: { is: :rw, required: true }
21
+ end
22
+
23
+ class Alien
24
+ include Name
25
+ include Address
26
+
27
+ has race: { is: :rw, required: true }
28
+ end
29
+
30
+ class FederationCitizen < Person
31
+ has starship: { is: :rw, required: true }
32
+ end
33
+
34
+ module Nameadress
35
+ include Name
36
+ include Address
37
+
38
+ has complement: { is: :rw, required: true}
39
+ end
40
+
41
+ class Enemy
42
+ include Nameadress
43
+
44
+ has weapons: { is: :rw, required: true}
45
+ end
46
+
47
+ class AlienX
48
+ include MooseX
49
+ include Name
50
+ include Address
51
+
52
+ has race: { is: :rw, required: true }
53
+ has x: { is: :rw, required: true }
54
+ end
55
+ end
56
+
57
+ describe RoleTest::Person do
58
+ it "should create a new instance" do
59
+ RoleTest::Person.new( name: "john", address: "vulcano", age: 18)
60
+ end
61
+
62
+ it "should has a name" do
63
+ a = RoleTest::Person.new(name: "john", address: "vulcano", age: 18)
64
+
65
+ a.name.should == "john"
66
+ a.address.should == "vulcano"
67
+ a.age.should == 18
68
+
69
+ a.name = "b"
70
+ a.address = "Earth"
71
+ a.age = 120
72
+
73
+ a.name.should == "b"
74
+ a.address.should == "Earth"
75
+ a.age.should == 120
76
+ end
77
+ end
78
+
79
+ describe RoleTest::Alien do
80
+ it "should create a new instance" do
81
+ RoleTest::Alien.new( name: "john", address: "vulcano", race: :klingon)
82
+ end
83
+
84
+ it "should has a name" do
85
+ a = RoleTest::Alien.new(name: "john", address: "vulcano", race: :klingon)
86
+
87
+ a.name.should == "john"
88
+ a.address.should == "vulcano"
89
+ a.race.should == :klingon
90
+
91
+ a.name = "b"
92
+ a.address = "Earth"
93
+ a.race = :borg
94
+
95
+ a.name.should == "b"
96
+ a.address.should == "Earth"
97
+ a.race.should == :borg
98
+ end
99
+ end
100
+
101
+ describe RoleTest::FederationCitizen do
102
+ it "should create a new instance" do
103
+ RoleTest::FederationCitizen.new( name: "john", address: "vulcano", age: 18, starship: :enterprise)
104
+ end
105
+
106
+ it "should has a name" do
107
+ a = RoleTest::FederationCitizen.new(name: "john", address: "vulcano", age: 18, starship: :enterprise)
108
+
109
+ a.name.should == "john"
110
+ a.address.should == "vulcano"
111
+ a.age.should == 18
112
+ a.starship.should == :enterprise
113
+
114
+ a.name = "b"
115
+ a.address = "Earth"
116
+ a.age = 120
117
+ a.starship = :yamato
118
+
119
+ a.name.should == "b"
120
+ a.address.should == "Earth"
121
+ a.age.should == 120
122
+ a.starship.should == :yamato
123
+ end
124
+ end
125
+
126
+ describe RoleTest::Enemy do
127
+ it "should create a new instance" do
128
+ RoleTest::Enemy.new( name: "john", address: "vulcano", complement: 1, weapons: :phaser)
129
+ end
130
+
131
+ it "should has a name" do
132
+ a = RoleTest::Enemy.new(name: "john", address: "vulcano", complement: 1, weapons: :phaser)
133
+
134
+ a.name.should == "john"
135
+ a.address.should == "vulcano"
136
+ a.weapons.should == :phaser
137
+ a.complement.should == 1
138
+
139
+ a.name = "b"
140
+ a.address = "Earth"
141
+ a.weapons = :disruptor
142
+ a.complement = 7
143
+
144
+ a.name.should == "b"
145
+ a.address.should == "Earth"
146
+ a.weapons.should == :disruptor
147
+ a.complement.should == 7
148
+ end
149
+ end
150
+
151
+ describe RoleTest::AlienX do
152
+ it "should create a new instance" do
153
+ RoleTest::AlienX.new( name: "john", address: "vulcano", race: :klingon, x: 0)
154
+ end
155
+
156
+ it "should has a name" do
157
+ a = RoleTest::AlienX.new(name: "john", address: "vulcano", race: :klingon, x: 0)
158
+
159
+ a.name.should == "john"
160
+ a.address.should == "vulcano"
161
+ a.race.should == :klingon
162
+ a.x.should == 0
163
+
164
+ a.name = "b"
165
+ a.address = "Earth"
166
+ a.race = :borg
167
+ a.x = -1
168
+
169
+ a.name.should == "b"
170
+ a.address.should == "Earth"
171
+ a.race.should == :borg
172
+ a.x.should == -1
173
+ end
174
+ end
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'moosex'
2
3
 
3
4
  class Baz
@@ -21,10 +21,6 @@ class CoerceTest
21
21
  coerce: lambda {|value| value.to_i },
22
22
  builder: lambda{|object| "2048" },
23
23
  }
24
-
25
- def trigger_attr(new_value)
26
- puts "change value of attribute to #{new_value}"
27
- end
28
24
  end
29
25
 
30
26
  describe "CoerceTest" do
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'moosex'
2
3
 
3
4
  class A
@@ -110,13 +110,12 @@ describe "Point" do
110
110
  end
111
111
 
112
112
  class Point3D < Point
113
-
114
- has x: { # override original attr!
115
- is: :rw,
116
- isa: Integer,
117
- default: 1,
113
+ has x: {
114
+ is: :rw, # Redefine attribute
115
+ isa: String, # should be String
116
+ default: "5", # default value is "5" (constant)
118
117
  }
119
-
118
+
120
119
  has z: {
121
120
  is: :rw, # read-write (mandatory)
122
121
  isa: Integer, # should be Integer
@@ -131,8 +130,8 @@ class Point3D < Point
131
130
  }
132
131
 
133
132
  def clear
134
- self.x= 0 # to run with type-check you must
135
- self.y= 0 # use the setter instad @x=
133
+ self.x= "0" # to run with type-check you must
134
+ self.y= 0 # use the setter instad @x=
136
135
  self.z= 0
137
136
  end
138
137
  end
@@ -141,27 +140,35 @@ describe "Point3D" do
141
140
  describe "should has an intelligent constructor" do
142
141
  it "without arguments, should initialize with default values" do
143
142
  p = Point3D.new
144
- p.x.should == 1
143
+ p.x.should == "5"
145
144
  p.y.should be_zero
146
145
  p.z.should be_zero
147
146
  p.what_is_the_color_of_this_point.should == :red
148
147
  end
149
148
 
150
149
  it "should initialize only y" do
151
- p = Point3D.new( x: 5 )
152
- p.x.should == 5
150
+ p = Point3D.new( x: "7" )
151
+ p.x.should == "7"
153
152
  p.y.should be_zero
154
153
  p.z.should be_zero
155
154
  p.what_is_the_color_of_this_point.should == :red
156
155
  end
157
156
 
158
157
  it "should initialize x and y" do
159
- p = Point3D.new( x: 5, y: 4, z: 8, color: :yellow)
160
- p.x.should == 5
158
+ p = Point3D.new( x: "5", y: 4, z: 8, color: :yellow)
159
+ p.x.should == "5"
161
160
  p.y.should == 4
162
161
  p.z.should == 8
163
162
  p.what_is_the_color_of_this_point.should == :yellow
164
163
  end
164
+
165
+ it "for x, with type check" do
166
+ p = Point3D.new
167
+ expect {
168
+ p.x = 666
169
+ }.to raise_error(MooseX::Types::TypeCheckError,
170
+ "isa check for x=: Type violation: value '666' (Fixnum) is not an instance of [Type String]")
171
+ end
165
172
  end
166
173
 
167
174
  describe "should create a getter and a setter" do
@@ -187,9 +194,9 @@ describe "Point3D" do
187
194
  end
188
195
 
189
196
  it "clear should clean attributes" do
190
- p = Point3D.new( x: 5, y: 4, z: 9)
197
+ p = Point3D.new( x: "5", y: 4, z: 9)
191
198
  p.clear
192
- p.x.should be_zero
199
+ p.x.should == "0"
193
200
  p.y.should be_zero
194
201
  p.z.should be_zero
195
202
  end
@@ -0,0 +1,83 @@
1
+ require 'moosex'
2
+
3
+ module ComplexRole
4
+ module Eq
5
+ include MooseX #.disable_warnings()
6
+
7
+ requires :equal
8
+
9
+ def no_equal(other)
10
+ ! self.equal(other)
11
+ end
12
+ end
13
+
14
+ module Valuable
15
+ include MooseX
16
+
17
+ has value: { is: :ro, required: true }
18
+ end
19
+
20
+ class Currency
21
+ include Valuable
22
+ include Eq # will warn unless disable_warnings was called.
23
+ # to avoid warnings, you should include after
24
+ # define all required modules,
25
+
26
+ def equal(other)
27
+ self.value == other.value
28
+ end
29
+
30
+ # include Eq # warning safe include
31
+ end
32
+
33
+ class Comparator
34
+ include MooseX
35
+
36
+ has compare_to: {
37
+ is: :ro,
38
+ isa: Eq,
39
+ handles: Eq,
40
+ }
41
+ end
42
+
43
+ module Wrapper
44
+ include Eq
45
+ end
46
+
47
+ class WrongClass
48
+ include Wrapper
49
+
50
+ has one: { is: :rw }
51
+ end
52
+ end
53
+
54
+ describe "ComplexRole::Currency" do
55
+ it "should compare based on value" do
56
+ c1 = ComplexRole::Currency.new( value: 12 )
57
+ c2 = ComplexRole::Currency.new( value: 12 )
58
+ c3 = ComplexRole::Currency.new( value: 24 )
59
+
60
+ c1.equal(c2).should be_true
61
+ c1.equal(c3).should be_false
62
+ end
63
+ end
64
+
65
+ describe ComplexRole::Comparator do
66
+ it "should compare two Currency instances" do
67
+ c1 = ComplexRole::Currency.new( value: 12 )
68
+ c2 = ComplexRole::Currency.new( value: 12 )
69
+ c3 = ComplexRole::Currency.new( value: 24 )
70
+
71
+ ComplexRole::Comparator.new(compare_to: c1).no_equal(c2).should be_false
72
+ ComplexRole::Comparator.new(compare_to: c1).no_equal(c3).should be_true
73
+ end
74
+ end
75
+
76
+ describe ComplexRole::WrongClass do
77
+ it "should die unless implement missing method" do
78
+ expect {
79
+ ComplexRole::WrongClass.new(one: 1, two: 2)
80
+ }.to raise_error(MooseX::RequiredMethodNotFoundError,
81
+ "you must implement method 'equal' in ComplexRole::WrongClass: required")
82
+ end
83
+ end
@@ -0,0 +1,7 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ # add_filter '/spec/'
4
+
5
+ add_group 'core', 'lib'
6
+ add_group 'test', 'spec'
7
+ 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.11
4
+ version: 0.0.12
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-04 00:00:00.000000000 Z
11
+ date: 2014-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: MooseX is an extension of Ruby object DSL. The main goal of MooseX is
56
70
  to make Ruby Object Oriented programming easier, more consistent, and less tedious.
57
71
  With MooseX you can think more about what you want to do and less about the mechanics
@@ -62,7 +76,9 @@ executables: []
62
76
  extensions: []
63
77
  extra_rdoc_files: []
64
78
  files:
79
+ - ".coveralls.yml"
65
80
  - ".gitignore"
81
+ - ".rspec"
66
82
  - ".travis.yml"
67
83
  - Changelog
68
84
  - Gemfile
@@ -75,6 +91,8 @@ files:
75
91
  - lib/moosex/version.rb
76
92
  - moosex.gemspec
77
93
  - samples/point.rb
94
+ - samples/roles.rb
95
+ - spec/baserole_spec.rb
78
96
  - spec/baz_spec.rb
79
97
  - spec/build_spec.rb
80
98
  - spec/buildargs_spec.rb
@@ -87,6 +105,8 @@ files:
87
105
  - spec/moosex_spec.rb
88
106
  - spec/point_spec.rb
89
107
  - spec/proxy_spec.rb
108
+ - spec/role_spec.rb
109
+ - spec/spec_helper.rb
90
110
  - spec/trigger_spec.rb
91
111
  - spec/types_spec.rb
92
112
  homepage: http://github.com/peczenyj/MooseX
@@ -114,6 +134,7 @@ signing_key:
114
134
  specification_version: 4
115
135
  summary: A postmodern object DSL for Ruby
116
136
  test_files:
137
+ - spec/baserole_spec.rb
117
138
  - spec/baz_spec.rb
118
139
  - spec/build_spec.rb
119
140
  - spec/buildargs_spec.rb
@@ -126,5 +147,8 @@ test_files:
126
147
  - spec/moosex_spec.rb
127
148
  - spec/point_spec.rb
128
149
  - spec/proxy_spec.rb
150
+ - spec/role_spec.rb
151
+ - spec/spec_helper.rb
129
152
  - spec/trigger_spec.rb
130
153
  - spec/types_spec.rb
154
+ has_rdoc: