attributor 2.6.1 → 3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +38 -26
- data/lib/attributor.rb +8 -7
- data/lib/attributor/attribute.rb +41 -25
- data/lib/attributor/dsl_compiler.rb +7 -1
- data/lib/attributor/type.rb +10 -8
- data/lib/attributor/types/collection.rb +49 -10
- data/lib/attributor/types/csv.rb +8 -1
- data/lib/attributor/types/hash.rb +45 -11
- data/lib/attributor/types/model.rb +13 -10
- data/lib/attributor/types/string.rb +4 -4
- data/lib/attributor/types/uri.rb +57 -0
- data/lib/attributor/version.rb +1 -1
- data/spec/attribute_spec.rb +136 -64
- data/spec/support/models.rb +7 -2
- data/spec/type_spec.rb +13 -3
- data/spec/types/collection_spec.rb +66 -19
- data/spec/types/csv_spec.rb +14 -3
- data/spec/types/hash_spec.rb +134 -10
- data/spec/types/ids_spec.rb +1 -1
- data/spec/types/model_spec.rb +78 -18
- data/spec/types/string_spec.rb +6 -8
- data/spec/types/uri_spec.rb +12 -0
- metadata +6 -3
data/lib/attributor/types/csv.rb
CHANGED
@@ -29,9 +29,16 @@ module Attributor
|
|
29
29
|
return collection.join(',')
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.describe(shallow=false, example: nil)
|
33
|
+
hash = super(shallow)
|
34
|
+
hash.delete(:member_attribute)
|
35
|
+
hash[:example] = example if example
|
36
|
+
hash
|
37
|
+
end
|
38
|
+
|
32
39
|
def self.family
|
33
40
|
Collection.family
|
34
41
|
end
|
35
|
-
|
42
|
+
|
36
43
|
end
|
37
44
|
end
|
@@ -1,4 +1,20 @@
|
|
1
1
|
module Attributor
|
2
|
+
class InvalidDefinition < StandardError
|
3
|
+
def initialize(type, cause)
|
4
|
+
type_name = if type.name
|
5
|
+
type.name
|
6
|
+
else
|
7
|
+
type.inspect
|
8
|
+
end
|
9
|
+
|
10
|
+
msg = "Structure definition for type #{type_name} is invalid. The following exception has occurred: #{cause.inspect}"
|
11
|
+
super(msg)
|
12
|
+
@cause = cause
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :cause
|
16
|
+
end
|
17
|
+
|
2
18
|
class Hash
|
3
19
|
|
4
20
|
MAX_EXAMPLE_DEPTH = 5
|
@@ -21,6 +37,8 @@ module Attributor
|
|
21
37
|
@key_attribute = Attribute.new(@key_type)
|
22
38
|
@value_attribute = Attribute.new(@value_type)
|
23
39
|
|
40
|
+
@error = false
|
41
|
+
|
24
42
|
|
25
43
|
def self.key_type=(key_type)
|
26
44
|
@key_type = Attributor.resolve_type(key_type)
|
@@ -37,7 +55,7 @@ module Attributor
|
|
37
55
|
def self.family
|
38
56
|
'hash'
|
39
57
|
end
|
40
|
-
|
58
|
+
|
41
59
|
@saved_blocks = []
|
42
60
|
@options = {allow_extra: false}
|
43
61
|
@keys = {}
|
@@ -54,14 +72,20 @@ module Attributor
|
|
54
72
|
@value_type = v
|
55
73
|
@key_attribute = Attribute.new(@key_type)
|
56
74
|
@value_attribute = Attribute.new(@value_type)
|
75
|
+
|
76
|
+
@error = false
|
57
77
|
end
|
58
78
|
end
|
59
79
|
|
60
80
|
def self.attributes(**options, &key_spec)
|
81
|
+
raise @error if @error
|
82
|
+
|
61
83
|
self.keys(options, &key_spec)
|
62
84
|
end
|
63
85
|
|
64
86
|
def self.keys(**options, &key_spec)
|
87
|
+
raise @error if @error
|
88
|
+
|
65
89
|
if block_given?
|
66
90
|
@saved_blocks << key_spec
|
67
91
|
@options.merge!(options)
|
@@ -86,8 +110,9 @@ module Attributor
|
|
86
110
|
map[k.downcase] = k
|
87
111
|
end
|
88
112
|
end
|
89
|
-
|
90
|
-
|
113
|
+
rescue => e
|
114
|
+
@error = InvalidDefinition.new(self, e)
|
115
|
+
raise
|
91
116
|
end
|
92
117
|
|
93
118
|
def self.dsl_class
|
@@ -134,10 +159,13 @@ module Attributor
|
|
134
159
|
|
135
160
|
|
136
161
|
def self.example_contents(context, parent, **values)
|
162
|
+
|
137
163
|
hash = ::Hash.new
|
138
164
|
example_depth = context.size
|
139
165
|
|
140
166
|
self.keys.each do |sub_attribute_name, sub_attribute|
|
167
|
+
|
168
|
+
|
141
169
|
if sub_attribute.attributes
|
142
170
|
# TODO: add option to raise an exception in this case?
|
143
171
|
next if example_depth > MAX_EXAMPLE_DEPTH
|
@@ -148,8 +176,8 @@ module Attributor
|
|
148
176
|
value = values.fetch(sub_attribute_name) do
|
149
177
|
sub_attribute.example(sub_context, parent: parent)
|
150
178
|
end
|
151
|
-
|
152
179
|
sub_attribute.load(value,sub_context)
|
180
|
+
|
153
181
|
end
|
154
182
|
|
155
183
|
|
@@ -160,6 +188,7 @@ module Attributor
|
|
160
188
|
end
|
161
189
|
|
162
190
|
def self.example(context=nil, **values)
|
191
|
+
|
163
192
|
if (key_type == Object && value_type == Object && self.keys.empty?)
|
164
193
|
return self.new
|
165
194
|
end
|
@@ -339,7 +368,7 @@ module Attributor
|
|
339
368
|
object.each do |k,v|
|
340
369
|
next if k == self.extra_keys
|
341
370
|
|
342
|
-
sub_context = self.generate_subcontext(
|
371
|
+
sub_context = self.generate_subcontext(context,k)
|
343
372
|
hash.set(k, v, context: sub_context, recurse: recurse)
|
344
373
|
end
|
345
374
|
|
@@ -365,19 +394,20 @@ module Attributor
|
|
365
394
|
object.validate(context)
|
366
395
|
end
|
367
396
|
|
368
|
-
def self.describe(shallow=false)
|
369
|
-
hash = super
|
397
|
+
def self.describe(shallow=false, example: nil)
|
398
|
+
hash = super(shallow)
|
370
399
|
|
371
400
|
if key_type
|
372
|
-
hash[:key] = {type: key_type.describe}
|
401
|
+
hash[:key] = {type: key_type.describe(true)}
|
373
402
|
end
|
374
403
|
|
375
404
|
if self.keys.any?
|
376
405
|
# Spit keys if it's the root or if it's an anonymous structures
|
377
|
-
if ( !shallow || self.name == nil)
|
406
|
+
if ( !shallow || self.name == nil)
|
378
407
|
# FIXME: change to :keys when the praxis doc browser supports displaying those. or josep's demo is over.
|
379
|
-
hash[:
|
380
|
-
|
408
|
+
hash[:attributes] = self.keys.each_with_object({}) do |(sub_name, sub_attribute), sub_attributes|
|
409
|
+
sub_example = example.get(sub_name) if example
|
410
|
+
sub_attributes[sub_name] = sub_attribute.describe(true, example: sub_example)
|
381
411
|
end
|
382
412
|
end
|
383
413
|
else
|
@@ -436,6 +466,10 @@ module Attributor
|
|
436
466
|
end
|
437
467
|
end
|
438
468
|
|
469
|
+
def delete(key)
|
470
|
+
@contents.delete(key)
|
471
|
+
end
|
472
|
+
|
439
473
|
attr_reader :validating, :dumping
|
440
474
|
|
441
475
|
def initialize(contents={})
|
@@ -6,11 +6,17 @@ module Attributor
|
|
6
6
|
undef :format
|
7
7
|
undef :test rescue nil
|
8
8
|
|
9
|
+
if RUBY_ENGINE =~ /^jruby/
|
10
|
+
# We are "forced" to require it here (in case hasn't been yet) to make sure the added methods have been applied
|
11
|
+
require 'java'
|
12
|
+
# Only to then delete them, to make sure we don't have them clashing with any attributes
|
13
|
+
undef java, javax, org, com
|
14
|
+
end
|
15
|
+
|
9
16
|
# Remove undesired methods inherited from Hash
|
10
17
|
undef :size
|
11
18
|
undef :keys
|
12
19
|
undef :values
|
13
|
-
undef :empty?
|
14
20
|
undef :has_key?
|
15
21
|
|
16
22
|
@key_type = Symbol
|
@@ -19,9 +25,10 @@ module Attributor
|
|
19
25
|
@key_attribute = Attribute.new(@key_type)
|
20
26
|
@value_attribute = Attribute.new(@value_type)
|
21
27
|
|
28
|
+
|
22
29
|
def self.inherited(klass)
|
23
30
|
k = self.key_type
|
24
|
-
ka = self.key_attribute
|
31
|
+
ka = self.key_attribute
|
25
32
|
|
26
33
|
v = self.value_type
|
27
34
|
va = self.value_attribute
|
@@ -35,6 +42,8 @@ module Attributor
|
|
35
42
|
|
36
43
|
@key_attribute = ka
|
37
44
|
@value_attribute = va
|
45
|
+
|
46
|
+
@error = false
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
@@ -66,12 +75,6 @@ module Attributor
|
|
66
75
|
end
|
67
76
|
end
|
68
77
|
|
69
|
-
def self.describe(shallow=false)
|
70
|
-
hash = super
|
71
|
-
hash[:attributes] = hash.delete :keys
|
72
|
-
hash
|
73
|
-
end
|
74
|
-
|
75
78
|
def self.check_option!(name, value)
|
76
79
|
case name
|
77
80
|
when :identity
|
@@ -89,7 +92,7 @@ module Attributor
|
|
89
92
|
end
|
90
93
|
|
91
94
|
def self.generate_subcontext(context, subname)
|
92
|
-
context + [subname]
|
95
|
+
context + [subname]
|
93
96
|
end
|
94
97
|
|
95
98
|
def self.example(context=nil, **values)
|
@@ -176,7 +179,7 @@ module Attributor
|
|
176
179
|
|
177
180
|
self.attributes.each_with_object({}) do |(name, value), result|
|
178
181
|
attribute = self.class.attributes[name]
|
179
|
-
|
182
|
+
|
180
183
|
# skip dumping undefined attributes
|
181
184
|
unless attribute
|
182
185
|
warn "WARNING: Trying to dump unknown attribute: #{name.inspect} with context: #{context.inspect}"
|
@@ -18,16 +18,16 @@ module Attributor
|
|
18
18
|
|
19
19
|
def self.example(context=nil, options:{})
|
20
20
|
if options[:regexp]
|
21
|
-
|
21
|
+
# It may fail to generate an example, see bug #72.
|
22
|
+
options[:regexp].gen rescue ('Failed to generate example for %s' % options[:regexp].inspect)
|
22
23
|
else
|
23
|
-
|
24
|
+
/\w+/.gen
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
28
|
def self.family
|
28
29
|
'string'
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
end
|
32
|
-
|
33
33
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Represents a href type.
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Attributor
|
5
|
+
class URI
|
6
|
+
include Attributor::Type
|
7
|
+
|
8
|
+
def self.family
|
9
|
+
String.family
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.valid_type?(value)
|
13
|
+
case value
|
14
|
+
when ::String, ::URI::Generic
|
15
|
+
true
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.native_type
|
22
|
+
return ::URI::Generic
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.example(context=nil, options={})
|
26
|
+
URI(/[:uri:]/.gen)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.load(value, context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
30
|
+
return nil if value.nil?
|
31
|
+
case value
|
32
|
+
when self.native_type
|
33
|
+
value
|
34
|
+
when ::String
|
35
|
+
URI(value)
|
36
|
+
else
|
37
|
+
raise CoercionError, context: context, from: value.class, to: self, value: value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.validate(value,context=Attributor::DEFAULT_ROOT_CONTEXT,attribute)
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_option!(name, definition)
|
46
|
+
# No options are supported
|
47
|
+
:unknown
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Randgen
|
54
|
+
def self.uri
|
55
|
+
"http://example.com/#{word}/#{rand(10 ** 9)}"
|
56
|
+
end
|
57
|
+
end
|
data/lib/attributor/version.rb
CHANGED
data/spec/attribute_spec.rb
CHANGED
@@ -93,6 +93,48 @@ describe Attributor::Attribute do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
end
|
96
|
+
|
97
|
+
context 'with an example' do
|
98
|
+
|
99
|
+
let(:attribute_options){ {} }
|
100
|
+
let(:example){ attribute.example }
|
101
|
+
subject(:described){ attribute.describe(false, example: example) }
|
102
|
+
|
103
|
+
context 'using a simple terminal type' do
|
104
|
+
let(:type) { String }
|
105
|
+
its(:keys){ should include(:example) }
|
106
|
+
it 'should have the passed example value' do
|
107
|
+
described.should have_key(:example)
|
108
|
+
described[:example].should eq(example)
|
109
|
+
end
|
110
|
+
it 'should have removed the example from the :type' do
|
111
|
+
described[:type].should_not have_key(:example)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'using a complex type' do
|
117
|
+
let(:type) { Cormorant }
|
118
|
+
its(:keys){ should_not include(:example) }
|
119
|
+
|
120
|
+
it 'Should see examples in the right places, depending on leaf/no-leaf types' do
|
121
|
+
# String, a leaf attribute type: should have example
|
122
|
+
name_attr = described[:type][:attributes][:name]
|
123
|
+
name_attr.should include(:example)
|
124
|
+
name_attr[:type].should_not include(:example)
|
125
|
+
|
126
|
+
# Struct, a non-leaf attribute type: shouldn't have example
|
127
|
+
ts_attr = described[:type][:attributes][:timestamps]
|
128
|
+
ts_attr.should_not include(:example)
|
129
|
+
ts_attr[:type].should_not include(:example)
|
130
|
+
|
131
|
+
# DateTime inside a Struct, a nested leaf attribute type: should have example
|
132
|
+
born_attr = ts_attr[:type][:attributes][:born_at]
|
133
|
+
born_attr.should include(:example)
|
134
|
+
born_attr[:type].should_not include(:example)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
96
138
|
end
|
97
139
|
|
98
140
|
|
@@ -135,10 +177,8 @@ describe Attributor::Attribute do
|
|
135
177
|
end
|
136
178
|
end
|
137
179
|
|
138
|
-
|
139
180
|
context 'example' do
|
140
181
|
let(:example) { nil }
|
141
|
-
let(:attribute_options) { {:example => example} }
|
142
182
|
|
143
183
|
context 'with nothing specified' do
|
144
184
|
let(:attribute_options) { {} }
|
@@ -151,108 +191,141 @@ describe Attributor::Attribute do
|
|
151
191
|
end
|
152
192
|
end
|
153
193
|
|
194
|
+
context 'with an attribute that has the values option set' do
|
195
|
+
let(:values) { ["one", "two"] }
|
196
|
+
let(:attribute_options) { {:values => values} }
|
197
|
+
it 'picks a random value' do
|
198
|
+
values.should include subject.example
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'deterministic examples' do
|
204
|
+
let(:example) { /\w+/ }
|
205
|
+
let(:attribute_options) { {:example => example} }
|
206
|
+
|
207
|
+
it 'can take a context to pre-seed the random number generator' do
|
208
|
+
example_1 = subject.example(['context'])
|
209
|
+
example_2 = subject.example(['context'])
|
210
|
+
|
211
|
+
example_1.should eq example_2
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'can take a context to pre-seed the random number generator' do
|
215
|
+
example_1 = subject.example(['context'])
|
216
|
+
example_2 = subject.example(['different context'])
|
217
|
+
|
218
|
+
example_1.should_not eq example_2
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'with an example option' do
|
223
|
+
let(:example){ "Bob" }
|
224
|
+
let(:attribute_options) { {example: example , regexp: /Bob/ } }
|
225
|
+
|
226
|
+
its(:example){ should == example }
|
227
|
+
|
228
|
+
context 'that is not valid' do
|
229
|
+
let(:example){ "Frank" }
|
230
|
+
it 'raises a validation error' do
|
231
|
+
expect{
|
232
|
+
subject.example
|
233
|
+
}.to raise_error(Attributor::AttributorException, /Error generating example/)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'example_from_options' do
|
240
|
+
let(:example) { nil }
|
241
|
+
let(:generated_example) { example }
|
242
|
+
let(:attribute_options) { {:example => example} }
|
243
|
+
let(:parent){ nil }
|
244
|
+
let(:context){ Attributor::DEFAULT_ROOT_CONTEXT}
|
245
|
+
|
246
|
+
subject(:example_result) { attribute.example_from_options( parent, context ) }
|
247
|
+
before do
|
248
|
+
attribute.should_receive(:load).with( generated_example , an_instance_of(Array) ).and_call_original
|
249
|
+
end
|
154
250
|
|
155
251
|
context 'with a string' do
|
156
252
|
let(:example) { "example" }
|
157
253
|
|
158
|
-
|
254
|
+
it { should be example }
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'with an integer' do
|
258
|
+
let(:type) { Attributor::Integer }
|
259
|
+
let(:example) { 5 }
|
260
|
+
it { should be example }
|
159
261
|
end
|
160
262
|
|
161
263
|
context 'with a regexp' do
|
162
264
|
let(:example) { /\w+/ }
|
163
|
-
|
265
|
+
let(:generated_example) { /\w+/.gen }
|
164
266
|
|
165
267
|
it 'calls #gen on the regexp' do
|
166
|
-
example.should_receive(:gen).
|
167
|
-
|
268
|
+
example.should_receive(:gen).and_return(generated_example)
|
269
|
+
|
270
|
+
example_result.should =~ example
|
168
271
|
end
|
169
272
|
|
170
273
|
context 'for a type with a non-String native_type' do
|
171
274
|
let(:type) { Attributor::Integer }
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
end
|
181
|
-
context 'usign a native Integer type' do
|
182
|
-
let(:example) { 5 }
|
183
|
-
it 'coerces the example value properly' do
|
184
|
-
type.should_receive(:load).and_call_original
|
185
|
-
subject.example.should be_kind_of(type.native_type)
|
186
|
-
end
|
275
|
+
let(:example) { /\d{5}/ }
|
276
|
+
let(:generated_example) { /\d{5}/.gen }
|
277
|
+
|
278
|
+
it 'coerces the example value properly' do
|
279
|
+
example.should_receive(:gen).and_return(generated_example)
|
280
|
+
type.should_receive(:load).and_call_original
|
281
|
+
|
282
|
+
example_result.should be_kind_of(type.native_type)
|
187
283
|
end
|
188
284
|
end
|
189
|
-
end
|
190
285
|
|
286
|
+
end
|
191
287
|
|
192
288
|
context 'with a proc' do
|
289
|
+
let(:parent){ Object.new }
|
290
|
+
|
193
291
|
context 'with one argument' do
|
194
292
|
let(:example) { lambda { |obj| 'ok' } }
|
195
|
-
let(:
|
293
|
+
let(:generated_example) { 'ok' }
|
196
294
|
|
197
295
|
before do
|
198
|
-
example.should_receive(:call).with(
|
296
|
+
example.should_receive(:call).with(parent).and_return(generated_example)
|
199
297
|
end
|
200
298
|
|
201
299
|
it 'passes any given parent through to the example proc' do
|
202
|
-
|
300
|
+
example_result.should == 'ok'
|
203
301
|
end
|
204
302
|
end
|
205
303
|
|
206
304
|
context 'with two arguments' do
|
207
305
|
let(:example) { lambda { |obj, context| "#{context} ok" } }
|
208
|
-
let(:
|
209
|
-
let(:
|
210
|
-
|
306
|
+
let(:generated_example) { "#{context} ok" }
|
307
|
+
let(:context){ ['some_context'] }
|
211
308
|
before do
|
212
|
-
example.should_receive(:call).with(
|
309
|
+
example.should_receive(:call).with(parent, context).and_return(generated_example)
|
213
310
|
end
|
214
311
|
|
215
312
|
it 'passes any given parent through to the example proc' do
|
216
|
-
|
313
|
+
example_result.should == "#{context} ok"
|
217
314
|
end
|
218
315
|
end
|
219
316
|
|
220
317
|
end
|
221
318
|
|
222
319
|
context 'with an array' do
|
223
|
-
let(:example) { ["one"
|
224
|
-
|
225
|
-
example.should include subject.example
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
context 'with an attribute that has the values option set' do
|
230
|
-
let(:values) { ["one", "two"] }
|
231
|
-
let(:attribute_options) { {:values => values} }
|
320
|
+
let(:example) { ["one"] }
|
321
|
+
let(:generated_example) { "one" }
|
232
322
|
it 'picks a random value' do
|
233
|
-
|
323
|
+
example.should_receive(:pick).and_call_original
|
324
|
+
example.should include example_result
|
234
325
|
end
|
235
326
|
|
236
327
|
end
|
237
328
|
|
238
|
-
context 'deterministic examples' do
|
239
|
-
let(:example) { /\w+/ }
|
240
|
-
it 'can take a context to pre-seed the random number generator' do
|
241
|
-
example_1 = subject.example(['context'])
|
242
|
-
example_2 = subject.example(['context'])
|
243
|
-
|
244
|
-
example_1.should eq example_2
|
245
|
-
end
|
246
|
-
|
247
|
-
it 'can take a context to pre-seed the random number generator' do
|
248
|
-
example_1 = subject.example(['context'])
|
249
|
-
example_2 = subject.example(['different context'])
|
250
|
-
|
251
|
-
example_1.should_not eq example_2
|
252
|
-
end
|
253
|
-
|
254
|
-
|
255
|
-
end
|
256
329
|
end
|
257
330
|
|
258
331
|
context 'load' do
|
@@ -286,7 +359,7 @@ describe Attributor::Attribute do
|
|
286
359
|
it { should == default_value}
|
287
360
|
|
288
361
|
end
|
289
|
-
|
362
|
+
|
290
363
|
context 'for a Proc-based default value' do
|
291
364
|
let(:context){ ["$"] }
|
292
365
|
subject(:result){ attribute.load(value,context) }
|
@@ -296,21 +369,21 @@ describe Attributor::Attribute do
|
|
296
369
|
let(:default_value) { proc { "no_params" } }
|
297
370
|
it { should == default_value.call }
|
298
371
|
end
|
299
|
-
|
372
|
+
|
300
373
|
context 'with 1 argument (the parent)' do
|
301
374
|
let(:default_value) { proc {|parent| "parent is fake: #{parent.class}" } }
|
302
375
|
it { should == "parent is fake: Attributor::FakeParent" }
|
303
376
|
end
|
304
|
-
|
377
|
+
|
305
378
|
context 'with 2 argument (the parent and the contents)' do
|
306
379
|
let(:default_value) { proc {|parent,context| "parent is fake: #{parent.class} and context is: #{context}" } }
|
307
380
|
it { should == "parent is fake: Attributor::FakeParent and context is: [\"$\"]"}
|
308
381
|
end
|
309
|
-
|
382
|
+
|
310
383
|
context 'which attempts to use the parent (which is not supported for the moment)' do
|
311
384
|
let(:default_value) { proc {|parent| "any parent method should spit out warning: [#{parent.something}]" } }
|
312
385
|
it "should output a warning" do
|
313
|
-
begin
|
386
|
+
begin
|
314
387
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
315
388
|
Kernel.should_receive(:warn).and_call_original
|
316
389
|
attribute.load(value,context).should == "any parent method should spit out warning: []"
|
@@ -638,7 +711,6 @@ describe Attributor::Attribute do
|
|
638
711
|
let(:type) { Attributor::Collection.of(member_type) }
|
639
712
|
let(:member_options) { {} }
|
640
713
|
|
641
|
-
|
642
714
|
context 'the member_attribute of that type' do
|
643
715
|
subject(:member_attribute) { attribute.type.member_attribute }
|
644
716
|
it { should be_kind_of(Attributor::Attribute)}
|