moosex 0.0.9 → 0.0.10
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 +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +285 -173
- data/lib/moosex.rb +56 -47
- data/lib/moosex/version.rb +1 -1
- data/moosex.gemspec +2 -2
- data/samples/point.rb +59 -0
- data/spec/baz_spec.rb +85 -0
- data/spec/build_spec.rb +23 -0
- data/spec/buildargs_spec.rb +106 -0
- data/spec/coerce_spec.rb +51 -0
- data/spec/foo_spec.rb +40 -0
- data/spec/lazy_spec.rb +126 -0
- data/spec/lol_spec.rb +42 -0
- data/spec/moosex_spec.rb +7 -746
- data/spec/point_spec.rb +201 -0
- data/spec/proxy_spec.rb +145 -0
- data/spec/trigger_spec.rb +83 -0
- metadata +26 -5
data/spec/coerce_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
|
3
|
+
class CoerceTest
|
4
|
+
include MooseX
|
5
|
+
|
6
|
+
has attribute_ro: {
|
7
|
+
is: :ro,
|
8
|
+
isa: Integer,
|
9
|
+
coerce: lambda {|value| value.to_i },
|
10
|
+
}
|
11
|
+
|
12
|
+
has attribute_rw: {
|
13
|
+
is: :rw,
|
14
|
+
isa: Integer,
|
15
|
+
coerce: lambda {|value| value.to_i },
|
16
|
+
}
|
17
|
+
|
18
|
+
has attribute_lazy: {
|
19
|
+
is: :lazy,
|
20
|
+
isa: Integer,
|
21
|
+
coerce: lambda {|value| value.to_i },
|
22
|
+
builder: lambda{|object| "2048" },
|
23
|
+
}
|
24
|
+
|
25
|
+
def trigger_attr(new_value)
|
26
|
+
puts "change value of attribute to #{new_value}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "CoerceTest" do
|
31
|
+
it "should coerce the argument using to_i on constructor" do
|
32
|
+
ct = CoerceTest.new(attribute_ro: "12")
|
33
|
+
ct.attribute_ro.should == 12
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should coerce the argument using to_i on constructor" do
|
37
|
+
ct = CoerceTest.new(attribute_rw: "12")
|
38
|
+
ct.attribute_rw.should == 12
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should coerce in the setter" do
|
42
|
+
ct = CoerceTest.new
|
43
|
+
ct.attribute_rw= "128"
|
44
|
+
ct.attribute_rw.should == 128
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should coerce from builder" do
|
48
|
+
ct = CoerceTest.new
|
49
|
+
ct.attribute_lazy.should == 2048
|
50
|
+
end
|
51
|
+
end
|
data/spec/foo_spec.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
|
3
|
+
class Foo
|
4
|
+
include MooseX
|
5
|
+
|
6
|
+
has bar: {
|
7
|
+
is: :rwp, # read-write-private (private setter)
|
8
|
+
required: true, # you should require in the constructor
|
9
|
+
}
|
10
|
+
|
11
|
+
has my_other_bar: {
|
12
|
+
is: :rw,
|
13
|
+
init_arg: :bar2
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "Foo" do
|
18
|
+
it "should require bar if necessary" do
|
19
|
+
expect {
|
20
|
+
Foo.new
|
21
|
+
}.to raise_error("attr \"bar\" is required")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should require bar if necessary" do
|
25
|
+
foo = Foo.new( bar: 123 )
|
26
|
+
foo.bar.should == 123
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not be possible update bar (setter private)" do
|
30
|
+
foo = Foo.new( bar: 123 )
|
31
|
+
expect {
|
32
|
+
foo.bar = 1024
|
33
|
+
}.to raise_error(NoMethodError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be possible initialize my_other_bar by bar2" do
|
37
|
+
foo = Foo.new( bar: 1, bar2: 555)
|
38
|
+
foo.my_other_bar.should == 555
|
39
|
+
end
|
40
|
+
end
|
data/spec/lazy_spec.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
|
3
|
+
class LazyFox
|
4
|
+
include MooseX
|
5
|
+
|
6
|
+
has something: {
|
7
|
+
is: :lazy
|
8
|
+
}
|
9
|
+
|
10
|
+
has other_thing: {
|
11
|
+
is: :rw,
|
12
|
+
lazy: true,
|
13
|
+
predicate: true,
|
14
|
+
clearer: true,
|
15
|
+
builder: :my_build_other_thing,
|
16
|
+
}
|
17
|
+
|
18
|
+
has lazy_attr_who_accepts_lambda: {
|
19
|
+
is: :lazy,
|
20
|
+
builder: lambda{ |object| object.something }
|
21
|
+
}
|
22
|
+
|
23
|
+
has lazy_with_default: {
|
24
|
+
is: :lazy,
|
25
|
+
default: 10,
|
26
|
+
clearer: true,
|
27
|
+
builder: lambda {|o| 1 },
|
28
|
+
}
|
29
|
+
|
30
|
+
has last_lazy_attr: {
|
31
|
+
is: :rw,
|
32
|
+
lazy: true,
|
33
|
+
}
|
34
|
+
|
35
|
+
def build_something
|
36
|
+
1024
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def my_build_other_thing
|
41
|
+
128
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "LazyFox" do
|
46
|
+
it "lazy attr should be act as a normal read only attr" do
|
47
|
+
l = LazyFox.new(something: 0)
|
48
|
+
l.something.should == 0
|
49
|
+
end
|
50
|
+
|
51
|
+
it "lazy attr should be read-only" do
|
52
|
+
l = LazyFox.new
|
53
|
+
expect{
|
54
|
+
l.something= 1
|
55
|
+
}.to raise_error(NoMethodError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "lazy: true but is :rw should act as a defered default value" do
|
59
|
+
l = LazyFox.new
|
60
|
+
l.other_thing.should == 128
|
61
|
+
l.other_thing = 9
|
62
|
+
l.other_thing.should == 9
|
63
|
+
end
|
64
|
+
|
65
|
+
it "lazy: true should not exists until necessary" do
|
66
|
+
l = LazyFox.new
|
67
|
+
l.has_other_thing?.should be_false
|
68
|
+
|
69
|
+
l.other_thing.should == 128
|
70
|
+
|
71
|
+
l.has_other_thing?.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "lazy: true :rw should build again" do
|
75
|
+
l = LazyFox.new
|
76
|
+
l.other_thing.should == 128
|
77
|
+
|
78
|
+
l.has_other_thing?.should be_true
|
79
|
+
|
80
|
+
l.clear_other_thing!
|
81
|
+
|
82
|
+
l.has_other_thing?.should be_false
|
83
|
+
|
84
|
+
l.other_thing.should == 128
|
85
|
+
|
86
|
+
l.has_other_thing?.should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "lazy attr should call build if necessary" do
|
90
|
+
l = LazyFox.new
|
91
|
+
l.something.should == 1024
|
92
|
+
l.other_thing.should == 128
|
93
|
+
end
|
94
|
+
|
95
|
+
it "lazy attr should accept lambda" do
|
96
|
+
l = LazyFox.new
|
97
|
+
l.lazy_attr_who_accepts_lambda.should == 1024
|
98
|
+
end
|
99
|
+
|
100
|
+
it "lazy attr should accept lambda (2)" do
|
101
|
+
l = LazyFox.new(something: 2)
|
102
|
+
l.lazy_attr_who_accepts_lambda.should == 2
|
103
|
+
end
|
104
|
+
|
105
|
+
it "lazy_with_default should be initialize with default value" do
|
106
|
+
l = LazyFox.new
|
107
|
+
l.lazy_with_default.should == 10
|
108
|
+
l.clear_lazy_with_default!
|
109
|
+
l.lazy_with_default.should == 1
|
110
|
+
end
|
111
|
+
|
112
|
+
it "last_lazy_attr will raise error without a builder" do
|
113
|
+
l = LazyFox.new
|
114
|
+
expect {
|
115
|
+
l.last_lazy_attr
|
116
|
+
}.to raise_error(NoMethodError)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "last_lazy_attr will not raise error with a builder" do
|
120
|
+
l = LazyFox.new
|
121
|
+
def l.build_last_lazy_attr
|
122
|
+
0
|
123
|
+
end
|
124
|
+
l.last_lazy_attr.should be_zero
|
125
|
+
end
|
126
|
+
end
|
data/spec/lol_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
|
3
|
+
class Lol
|
4
|
+
include MooseX
|
5
|
+
|
6
|
+
has [:a, :b], { # define attributes a and b
|
7
|
+
is: :ro, # with same set of properties
|
8
|
+
default: 0,
|
9
|
+
}
|
10
|
+
|
11
|
+
has c: { # alternative syntax to be
|
12
|
+
is: :ro, # more similar to Moo/Moose
|
13
|
+
default: 1,
|
14
|
+
predicate: :can_haz_c?, # custom predicate
|
15
|
+
clearer: "desintegrate_c", # force coerce to symbol
|
16
|
+
}
|
17
|
+
|
18
|
+
has [:d, :e] => {
|
19
|
+
is: "ro", # can coerce from strings
|
20
|
+
default: 2,
|
21
|
+
required: true,
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "Lol" do
|
26
|
+
it "Lol should has five arguments" do
|
27
|
+
lol = Lol.new(a: 5, d: -1)
|
28
|
+
lol.a.should == 5
|
29
|
+
lol.b.should be_zero
|
30
|
+
lol.c.should == 1
|
31
|
+
lol.d.should == -1
|
32
|
+
lol.e.should == 2
|
33
|
+
end
|
34
|
+
|
35
|
+
it "Lol should support custom predicate and clearer" do
|
36
|
+
lol = Lol.new(a: 5, d: -1)
|
37
|
+
|
38
|
+
lol.can_haz_c?.should be_true
|
39
|
+
lol.desintegrate_c
|
40
|
+
lol.can_haz_c?.should be_false
|
41
|
+
end
|
42
|
+
end
|
data/spec/moosex_spec.rb
CHANGED
@@ -1,755 +1,16 @@
|
|
1
1
|
require 'moosex'
|
2
2
|
|
3
|
-
class
|
3
|
+
class A
|
4
4
|
include MooseX
|
5
|
-
|
6
|
-
has x: {
|
7
|
-
is: :rw, # read-write (mandatory)
|
8
|
-
isa: Integer, # should be Integer
|
9
|
-
default: 0, # default value is 0 (constant)
|
10
|
-
}
|
11
|
-
|
12
|
-
has y: {
|
13
|
-
is: :rw,
|
14
|
-
isa: Integer,
|
15
|
-
default: lambda { 0 }, # you should specify a lambda
|
16
|
-
}
|
17
|
-
|
18
|
-
def clear
|
19
|
-
self.x= 0 # to run with type-check you must
|
20
|
-
self.y= 0 # use the setter instad @x=
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "Point" do
|
25
|
-
describe "should has an intelligent constructor" do
|
26
|
-
it "without arguments, should initialize with default values" do
|
27
|
-
p = Point.new
|
28
|
-
p.x.should be_zero
|
29
|
-
p.y.should be_zero
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should initialize only y" do
|
33
|
-
p = Point.new( x: 5 )
|
34
|
-
p.x.should == 5
|
35
|
-
p.y.should be_zero
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should initialize x and y" do
|
39
|
-
p = Point.new( x: 5, y: 4)
|
40
|
-
p.x.should == 5
|
41
|
-
p.y.should == 4
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "should create a getter and a setter" do
|
46
|
-
it "for x" do
|
47
|
-
p = Point.new
|
48
|
-
p.x= 5
|
49
|
-
p.x.should == 5
|
50
|
-
end
|
51
|
-
|
52
|
-
it "for x, with type check" do
|
53
|
-
p = Point.new
|
54
|
-
expect {
|
55
|
-
p.x = "lol"
|
56
|
-
}.to raise_error('isa check for "x" failed: is not instance of Integer!')
|
57
|
-
end
|
58
|
-
|
59
|
-
it "for x, with type check" do
|
60
|
-
expect {
|
61
|
-
Point.new(x: "lol")
|
62
|
-
}.to raise_error('isa check for "x" failed: is not instance of Integer!')
|
63
|
-
end
|
64
|
-
|
65
|
-
it "clear should clean attributes" do
|
66
|
-
p = Point.new( x: 5, y: 4)
|
67
|
-
p.clear
|
68
|
-
p.x.should be_zero
|
69
|
-
p.y.should be_zero
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Foo
|
75
|
-
include MooseX
|
76
|
-
|
77
|
-
has bar: {
|
78
|
-
is: :rwp, # read-write-private (private setter)
|
79
|
-
required: true, # you should require in the constructor
|
80
|
-
}
|
81
|
-
|
82
|
-
has my_other_bar: {
|
83
|
-
is: :rw,
|
84
|
-
init_arg: :bar2
|
85
|
-
}
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "Foo" do
|
89
|
-
it "should require bar if necessary" do
|
90
|
-
expect {
|
91
|
-
Foo.new
|
92
|
-
}.to raise_error("attr \"bar\" is required")
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should require bar if necessary" do
|
96
|
-
foo = Foo.new( bar: 123 )
|
97
|
-
foo.bar.should == 123
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should not be possible update bar (setter private)" do
|
101
|
-
foo = Foo.new( bar: 123 )
|
102
|
-
expect {
|
103
|
-
foo.bar = 1024
|
104
|
-
}.to raise_error(NoMethodError)
|
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
|
111
|
-
end
|
112
|
-
|
113
|
-
class Baz
|
114
|
-
include MooseX
|
115
|
-
|
116
|
-
has bam: {
|
117
|
-
is: :ro, # read-only, you should specify in new only
|
118
|
-
isa: lambda do |bam| # you should add your own validator
|
119
|
-
raise 'bam should be less than 100' if bam > 100
|
120
|
-
end,
|
121
|
-
required: true,
|
122
|
-
}
|
123
|
-
|
124
|
-
has boom: {
|
125
|
-
is: :rw,
|
126
|
-
predicate: true, # add has_boom? method, ask if the attribute is unset
|
127
|
-
clearer: true, # add reset_boom! method, unset the attribute
|
128
|
-
}
|
129
|
-
end
|
130
|
-
|
131
|
-
describe "Baz" do
|
132
|
-
it "should require bam if necessary" do
|
133
|
-
baz = Baz.new( bam: 99 )
|
134
|
-
baz.bam.should == 99
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should not be possible update baz (read only)" do
|
138
|
-
baz = Baz.new( bam: 99 )
|
139
|
-
expect {
|
140
|
-
baz.bam = 1024
|
141
|
-
}.to raise_error(NoMethodError)
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should run the lambda isa" do
|
145
|
-
expect {
|
146
|
-
Baz.new( bam: 199 )
|
147
|
-
}.to raise_error(/bam should be less than 100/)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "rw acessor should has nil value, supports predicate" do
|
151
|
-
baz = Baz.new( bam: 99 )
|
152
|
-
|
153
|
-
baz.has_boom?.should be_false
|
154
|
-
baz.boom.should be_nil
|
155
|
-
baz.boom= 0
|
156
|
-
baz.has_boom?.should be_true
|
157
|
-
baz.boom.should be_zero
|
158
|
-
end
|
159
|
-
|
160
|
-
it "rw acessor should has nil value, supports clearer" do
|
161
|
-
baz = Baz.new( bam: 99, boom: 0 )
|
162
|
-
|
163
|
-
baz.has_boom?.should be_true
|
164
|
-
baz.boom.should be_zero
|
165
|
-
|
166
|
-
baz.reset_boom!
|
167
|
-
|
168
|
-
baz.has_boom?.should be_false
|
169
|
-
baz.boom.should be_nil
|
170
|
-
end
|
171
|
-
|
172
|
-
it "should be possible call the clearer twice" do
|
173
|
-
baz = Baz.new( bam: 99, boom: 0 )
|
174
|
-
|
175
|
-
baz.reset_boom!
|
176
|
-
baz.reset_boom!
|
177
|
-
|
178
|
-
baz.has_boom?.should be_false
|
179
|
-
baz.boom.should be_nil
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
class Lol
|
184
|
-
include MooseX
|
185
|
-
|
186
|
-
has [:a, :b], { # define attributes a and b
|
187
|
-
is: :ro, # with same set of properties
|
188
|
-
default: 0,
|
189
|
-
}
|
190
|
-
|
191
|
-
has c: { # alternative syntax to be
|
192
|
-
is: :ro, # more similar to Moo/Moose
|
193
|
-
default: 1,
|
194
|
-
predicate: :can_haz_c?, # custom predicate
|
195
|
-
clearer: "desintegrate_c", # force coerce to symbol
|
196
|
-
}
|
197
|
-
|
198
|
-
has [:d, :e] => {
|
199
|
-
is: "ro", # can coerce from strings
|
200
|
-
default: 2,
|
201
|
-
required: true,
|
202
|
-
}
|
203
|
-
end
|
204
|
-
|
205
|
-
describe "Lol" do
|
206
|
-
it "Lol should has five arguments" do
|
207
|
-
lol = Lol.new(a: 5, d: -1)
|
208
|
-
lol.a.should == 5
|
209
|
-
lol.b.should be_zero
|
210
|
-
lol.c.should == 1
|
211
|
-
lol.d.should == -1
|
212
|
-
lol.e.should == 2
|
213
|
-
end
|
214
|
-
|
215
|
-
it "Lol should support custom predicate and clearer" do
|
216
|
-
lol = Lol.new(a: 5, d: -1)
|
217
|
-
|
218
|
-
lol.can_haz_c?.should be_true
|
219
|
-
lol.desintegrate_c
|
220
|
-
lol.can_haz_c?.should be_false
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
class ProxyToTarget
|
225
|
-
include MooseX
|
226
|
-
|
227
|
-
has target: {
|
228
|
-
is: :ro,
|
229
|
-
default: lambda { Target.new }, # default, new instace of Target
|
230
|
-
handles: { # handles is for delegation,
|
231
|
-
my_method_x: :method_x, # inject methods with new names
|
232
|
-
my_method_y: :method_y, # old => obj.target.method_x
|
233
|
-
}, # now => obj.my_method_x
|
234
|
-
}
|
235
|
-
end
|
236
|
-
|
237
|
-
module TargetModule
|
238
|
-
def method_x; 1024; end # works with simple methods
|
239
|
-
def method_y(a,b,c); a + b + c; end # or methods with arguments
|
240
|
-
end
|
241
|
-
|
242
|
-
class Target
|
243
|
-
include TargetModule
|
244
|
-
end
|
245
|
-
|
246
|
-
describe "ProxyToTarget" do
|
247
|
-
it "should delegate method_x to the target" do
|
248
|
-
p = ProxyToTarget.new
|
249
|
-
|
250
|
-
p.target.method_x.should == 1024
|
251
|
-
p.my_method_x.should == 1024
|
252
|
-
end
|
253
|
-
|
254
|
-
it "should delegate method_y to the target" do
|
255
|
-
p = ProxyToTarget.new
|
256
|
-
|
257
|
-
p.target.method_y(1,2,3).should == 6
|
258
|
-
p.my_method_y(1,2,3).should == 6
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
class ProxyToTargetUsingArrayOfMethods
|
263
|
-
include MooseX
|
264
|
-
|
265
|
-
has targetz: {
|
266
|
-
is: :ro,
|
267
|
-
default: lambda { Target.new },
|
268
|
-
handles: [
|
269
|
-
:method_x, :method_y # will inject all methods with same name
|
270
|
-
]
|
271
|
-
}
|
272
|
-
end
|
273
|
-
|
274
|
-
describe "ProxyToTargetUsingArrayOfMethods" do
|
275
|
-
it "should delegate method_x to the target" do
|
276
|
-
p = ProxyToTargetUsingArrayOfMethods.new
|
277
|
-
|
278
|
-
p.targetz.method_x.should == 1024
|
279
|
-
p.method_x.should == 1024
|
280
|
-
end
|
281
|
-
|
282
|
-
it "should delegate method_y to the target" do
|
283
|
-
p = ProxyToTargetUsingArrayOfMethods.new
|
284
|
-
|
285
|
-
p.targetz.method_y(1,2,3).should == 6
|
286
|
-
p.method_y(1,2,3).should == 6
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
class ProxyToTargetUsingSingleMethod
|
291
|
-
include MooseX
|
292
|
-
|
293
|
-
has target: {
|
294
|
-
is: :ro,
|
295
|
-
default: lambda { Target.new },
|
296
|
-
handles: "method_x" # coerce to an array of symbols
|
297
|
-
}
|
298
|
-
end
|
299
|
-
|
300
|
-
describe "ProxyToTargetUsingSingleMethod" do
|
301
|
-
it "should delegate method_x to the target" do
|
302
|
-
p = ProxyToTargetUsingSingleMethod.new
|
303
|
-
|
304
|
-
p.target.method_x.should == 1024
|
305
|
-
p.method_x.should == 1024
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
class ProxyToTargetUsingModule
|
310
|
-
include MooseX
|
311
|
-
|
312
|
-
has target: {
|
313
|
-
is: :ro,
|
314
|
-
default: lambda { Target.new },
|
315
|
-
handles: TargetModule # will import all methods from module
|
316
|
-
}
|
317
|
-
end
|
318
|
-
|
319
|
-
describe "ProxyToTargetUsingModule" do
|
320
|
-
it "should delegate method_x to the target" do
|
321
|
-
p = ProxyToTargetUsingModule.new
|
322
|
-
|
323
|
-
p.target.method_x.should == 1024
|
324
|
-
p.method_x.should == 1024
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should delegate method_y to the target" do
|
328
|
-
p = ProxyToTargetUsingModule.new
|
329
|
-
|
330
|
-
p.target.method_y(1,2,3).should == 6
|
331
|
-
p.method_y(1,2,3).should == 6
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
class ProxyToTargetUsingClass
|
336
|
-
include MooseX
|
337
|
-
|
338
|
-
has target: {
|
339
|
-
is: :ro,
|
340
|
-
default: lambda { Target.new },
|
341
|
-
handles: Target # will use only public methods on Target class
|
342
|
-
} # exclude methods from superclass
|
343
|
-
end
|
344
|
-
|
345
|
-
describe "ProxyToTargetUsingClass" do
|
346
|
-
it "should delegate method_x to the target" do
|
347
|
-
p = ProxyToTargetUsingClass.new
|
348
|
-
|
349
|
-
p.target.method_x.should == 1024
|
350
|
-
p.method_x.should == 1024
|
351
|
-
end
|
352
|
-
|
353
|
-
it "should delegate method_y to the target" do
|
354
|
-
p = ProxyToTargetUsingClass.new
|
355
|
-
|
356
|
-
p.target.method_y(1,2,3).should == 6
|
357
|
-
p.method_y(1,2,3).should == 6
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
class Point3D < Point
|
362
|
-
|
363
|
-
has x: { # override original attr!
|
364
|
-
is: :rw,
|
365
|
-
isa: Integer,
|
366
|
-
default: 1,
|
367
|
-
}
|
368
|
-
|
369
|
-
has z: {
|
370
|
-
is: :rw, # read-write (mandatory)
|
371
|
-
isa: Integer, # should be Integer
|
372
|
-
default: 0, # default value is 0 (constant)
|
373
|
-
}
|
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
|
-
|
382
|
-
def clear
|
383
|
-
self.x= 0 # to run with type-check you must
|
384
|
-
self.y= 0 # use the setter instad @x=
|
385
|
-
self.z= 0
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
describe "Point3D" do
|
390
|
-
describe "should has an intelligent constructor" do
|
391
|
-
it "without arguments, should initialize with default values" do
|
392
|
-
p = Point3D.new
|
393
|
-
p.x.should == 1
|
394
|
-
p.y.should be_zero
|
395
|
-
p.z.should be_zero
|
396
|
-
p.what_is_the_color_of_this_point.should == :red
|
397
|
-
end
|
398
|
-
|
399
|
-
it "should initialize only y" do
|
400
|
-
p = Point3D.new( x: 5 )
|
401
|
-
p.x.should == 5
|
402
|
-
p.y.should be_zero
|
403
|
-
p.z.should be_zero
|
404
|
-
p.what_is_the_color_of_this_point.should == :red
|
405
|
-
end
|
406
|
-
|
407
|
-
it "should initialize x and y" do
|
408
|
-
p = Point3D.new( x: 5, y: 4, z: 8, color: :yellow)
|
409
|
-
p.x.should == 5
|
410
|
-
p.y.should == 4
|
411
|
-
p.z.should == 8
|
412
|
-
p.what_is_the_color_of_this_point.should == :yellow
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
describe "should create a getter and a setter" do
|
417
|
-
it "for z" do
|
418
|
-
p = Point3D.new
|
419
|
-
p.z= 5
|
420
|
-
p.z.should == 5
|
421
|
-
end
|
422
|
-
|
423
|
-
it "for z, with type check" do
|
424
|
-
p = Point3D.new
|
425
|
-
expect {
|
426
|
-
p.z = "lol"
|
427
|
-
}.to raise_error('isa check for "z" failed: is not instance of Integer!')
|
428
|
-
end
|
429
|
-
|
430
|
-
it "for z, with type check" do
|
431
|
-
expect {
|
432
|
-
Point3D.new(z: "lol")
|
433
|
-
}.to raise_error('isa check for "z" failed: is not instance of Integer!')
|
434
|
-
end
|
435
|
-
|
436
|
-
it "clear should clean attributes" do
|
437
|
-
p = Point3D.new( x: 5, y: 4, z: 9)
|
438
|
-
p.clear
|
439
|
-
p.x.should be_zero
|
440
|
-
p.y.should be_zero
|
441
|
-
p.z.should be_zero
|
442
|
-
end
|
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
|
495
5
|
end
|
496
6
|
|
497
|
-
describe "
|
498
|
-
it "
|
499
|
-
|
500
|
-
l.something.should == 0
|
7
|
+
describe "MooseX" do
|
8
|
+
it "should contains has method" do
|
9
|
+
A.methods.include?(:has).should be_true
|
501
10
|
end
|
502
11
|
|
503
|
-
it "
|
504
|
-
|
505
|
-
|
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
|
579
|
-
|
580
|
-
class CoerceTest
|
581
|
-
include MooseX
|
582
|
-
|
583
|
-
has attribute_ro: {
|
584
|
-
is: :ro,
|
585
|
-
isa: Integer,
|
586
|
-
coerce: lambda {|value| value.to_i },
|
587
|
-
}
|
588
|
-
|
589
|
-
has attribute_rw: {
|
590
|
-
is: :rw,
|
591
|
-
isa: Integer,
|
592
|
-
coerce: lambda {|value| value.to_i },
|
593
|
-
}
|
594
|
-
|
595
|
-
has attribute_lazy: {
|
596
|
-
is: :lazy,
|
597
|
-
isa: Integer,
|
598
|
-
coerce: lambda {|value| value.to_i },
|
599
|
-
builder: lambda{|object| "2048" },
|
600
|
-
}
|
601
|
-
|
602
|
-
def trigger_attr(new_value)
|
603
|
-
puts "change value of attribute to #{new_value}"
|
604
|
-
end
|
605
|
-
end
|
606
|
-
|
607
|
-
describe "CoerceTest" do
|
608
|
-
it "should coerce the argument using to_i on constructor" do
|
609
|
-
ct = CoerceTest.new(attribute_ro: "12")
|
610
|
-
ct.attribute_ro.should == 12
|
611
|
-
end
|
612
|
-
|
613
|
-
it "should coerce the argument using to_i on constructor" do
|
614
|
-
ct = CoerceTest.new(attribute_rw: "12")
|
615
|
-
ct.attribute_rw.should == 12
|
616
|
-
end
|
617
|
-
|
618
|
-
it "should coerce in the setter" do
|
619
|
-
ct = CoerceTest.new
|
620
|
-
ct.attribute_rw= "128"
|
621
|
-
ct.attribute_rw.should == 128
|
622
|
-
end
|
623
|
-
|
624
|
-
it "should coerce from builder" do
|
625
|
-
ct = CoerceTest.new
|
626
|
-
ct.attribute_lazy.should == 2048
|
627
|
-
end
|
628
|
-
end
|
629
|
-
|
630
|
-
class TriggerTest
|
631
|
-
include MooseX
|
632
|
-
|
633
|
-
has logger: {
|
634
|
-
is: :ro
|
635
|
-
}
|
636
|
-
|
637
|
-
has attr_with_trigger: {
|
638
|
-
is: :rw,
|
639
|
-
trigger: :my_method,
|
640
|
-
}
|
641
|
-
|
642
|
-
has attr_with_trigger_ro: {
|
643
|
-
is: :ro,
|
644
|
-
trigger: :my_method,
|
645
|
-
}
|
646
|
-
|
647
|
-
has attr_with_default: {
|
648
|
-
is: :rw,
|
649
|
-
trigger: lambda do |object, new_value|
|
650
|
-
object.logger.log "will update attr_with_trigger with new value #{new_value}"
|
651
|
-
end,
|
652
|
-
default: 1,
|
653
|
-
}
|
654
|
-
|
655
|
-
has attr_lazy_trigger: {
|
656
|
-
is: :lazy,
|
657
|
-
trigger: :my_method,
|
658
|
-
builder: lambda{ |x| 1},
|
659
|
-
}
|
660
|
-
|
661
|
-
def my_method(new_value)
|
662
|
-
logger.log "will update attr_with_trigger with new value #{new_value}"
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
describe "TriggerTest" do
|
667
|
-
it "should call trigger on constructor" do
|
668
|
-
log = double
|
669
|
-
log.should_receive(:log)
|
670
|
-
t = TriggerTest.new(attr_with_trigger: 1, logger: log)
|
671
|
-
|
672
|
-
end
|
673
|
-
|
674
|
-
it "should call trigger on constructor (ro)" do
|
675
|
-
log = double
|
676
|
-
log.should_receive(:log)
|
677
|
-
t = TriggerTest.new(attr_with_trigger_ro: 1, logger: log)
|
678
|
-
|
679
|
-
end
|
680
|
-
|
681
|
-
it "should NOT call trigger on constructor (with default)" do
|
682
|
-
log = double
|
683
|
-
log.should_not_receive(:log)
|
684
|
-
t = TriggerTest.new(logger: log)
|
685
|
-
end
|
686
|
-
|
687
|
-
it "should NOT call trigger on constructor (with default)" do
|
688
|
-
log = double
|
689
|
-
log.should_receive(:log)
|
690
|
-
t = TriggerTest.new(logger: log)
|
691
|
-
|
692
|
-
t.attr_with_default = 1
|
693
|
-
end
|
694
|
-
|
695
|
-
it "should call trigger on setter" do
|
696
|
-
log = double
|
697
|
-
log.should_receive(:log)
|
698
|
-
t = TriggerTest.new(logger: log)
|
699
|
-
|
700
|
-
t.attr_with_trigger = 1
|
701
|
-
end
|
702
|
-
|
703
|
-
it "should call trigger on setter" do
|
704
|
-
log = double
|
705
|
-
log.should_receive(:log)
|
706
|
-
t = TriggerTest.new(logger: log)
|
707
|
-
|
708
|
-
t.attr_lazy_trigger.should == 1
|
709
|
-
end
|
710
|
-
end
|
711
|
-
|
712
|
-
class BuildArgsExample
|
713
|
-
include MooseX
|
714
|
-
|
715
|
-
has [:x, :y], {
|
716
|
-
is: :rw,
|
717
|
-
required: true,
|
718
|
-
}
|
719
|
-
|
720
|
-
def BUILDARGS(args)
|
721
|
-
args[:x] = 1024
|
722
|
-
args[:y] = - args[:y]
|
723
|
-
args
|
724
|
-
end
|
725
|
-
end
|
726
|
-
|
727
|
-
describe "BuildArgsExample" do
|
728
|
-
it "should create the object" do
|
729
|
-
ex = BuildArgsExample.new(x: 10, y: -2)
|
730
|
-
ex.x.should == 1024
|
731
|
-
ex.y.should == 2
|
732
|
-
end
|
733
|
-
end
|
734
|
-
|
735
|
-
class BuildExample
|
736
|
-
include MooseX
|
737
|
-
|
738
|
-
has [:x, :y], {
|
739
|
-
is: :rw,
|
740
|
-
required: true,
|
741
|
-
}
|
742
|
-
def BUILD
|
743
|
-
if self.x == self.y
|
744
|
-
raise "invalid: you should use x != y"
|
745
|
-
end
|
746
|
-
end
|
747
|
-
end
|
748
|
-
|
749
|
-
describe "BuildExample" do
|
750
|
-
it "should raise exception on build" do
|
751
|
-
expect {
|
752
|
-
BuildExample.new(x: 0, y: 0)
|
753
|
-
}.to raise_error(/invalid: you should use x != y/)
|
12
|
+
it "should be possible create one single instance" do
|
13
|
+
a = A.new
|
14
|
+
a.is_a?(A).should be_true
|
754
15
|
end
|
755
16
|
end
|