attributor 2.6.1 → 3.0
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/.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)}
|