attributor 5.4 → 6.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/lib/attributor/attribute.rb +101 -84
  4. data/lib/attributor/extras/field_selector.rb +4 -0
  5. data/lib/attributor/families/numeric.rb +19 -6
  6. data/lib/attributor/families/temporal.rb +16 -9
  7. data/lib/attributor/hash_dsl_compiler.rb +6 -5
  8. data/lib/attributor/type.rb +26 -3
  9. data/lib/attributor/types/bigdecimal.rb +6 -1
  10. data/lib/attributor/types/boolean.rb +5 -0
  11. data/lib/attributor/types/collection.rb +19 -0
  12. data/lib/attributor/types/csv.rb +4 -0
  13. data/lib/attributor/types/date.rb +7 -1
  14. data/lib/attributor/types/date_time.rb +7 -1
  15. data/lib/attributor/types/float.rb +4 -3
  16. data/lib/attributor/types/hash.rb +86 -23
  17. data/lib/attributor/types/integer.rb +7 -1
  18. data/lib/attributor/types/model.rb +9 -21
  19. data/lib/attributor/types/object.rb +5 -0
  20. data/lib/attributor/types/polymorphic.rb +0 -1
  21. data/lib/attributor/types/string.rb +19 -0
  22. data/lib/attributor/types/symbol.rb +5 -0
  23. data/lib/attributor/types/tempfile.rb +4 -0
  24. data/lib/attributor/types/time.rb +6 -2
  25. data/lib/attributor/types/uri.rb +8 -0
  26. data/lib/attributor/version.rb +1 -1
  27. data/lib/attributor.rb +3 -7
  28. data/spec/attribute_spec.rb +148 -124
  29. data/spec/extras/field_selector/field_selector_spec.rb +9 -0
  30. data/spec/hash_dsl_compiler_spec.rb +5 -5
  31. data/spec/spec_helper.rb +0 -2
  32. data/spec/support/integers.rb +7 -0
  33. data/spec/support/models.rb +7 -7
  34. data/spec/types/bigdecimal_spec.rb +8 -0
  35. data/spec/types/boolean_spec.rb +10 -0
  36. data/spec/types/collection_spec.rb +16 -0
  37. data/spec/types/date_spec.rb +9 -0
  38. data/spec/types/date_time_spec.rb +9 -0
  39. data/spec/types/float_spec.rb +8 -0
  40. data/spec/types/hash_spec.rb +181 -22
  41. data/spec/types/integer_spec.rb +9 -0
  42. data/spec/types/model_spec.rb +7 -1
  43. data/spec/types/string_spec.rb +10 -0
  44. data/spec/types/temporal_spec.rb +5 -1
  45. data/spec/types/time_spec.rb +9 -0
  46. data/spec/types/uri_spec.rb +9 -0
  47. metadata +5 -6
  48. data/lib/attributor/attribute_resolver.rb +0 -111
  49. data/spec/attribute_resolver_spec.rb +0 -237
@@ -1,237 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
-
3
- describe Attributor::AttributeResolver do
4
- let(:value) { /\w+/.gen }
5
-
6
- context 'registering and querying simple values' do
7
- let(:name) { 'string_value' }
8
- before { subject.register(name, value) }
9
-
10
- it 'works' do
11
- expect(subject.query(name)).to be value
12
- end
13
- end
14
-
15
- context 'querying and registering nested values' do
16
- let(:one) { double(two: value) }
17
- let(:key) { 'one.two' }
18
- before { subject.register('one', one) }
19
-
20
- it 'works' do
21
- expect(subject.query(key)).to be value
22
- end
23
- end
24
-
25
- context 'querying nested values from models' do
26
- let(:instance) { double('instance', ssh_key: ssh_key) }
27
- let(:ssh_key) { double('ssh_key', name: value) }
28
- let(:key) { 'instance.ssh_key.name' }
29
-
30
- before { subject.register('instance', instance) }
31
-
32
- it 'works' do
33
- expect(subject.query('instance')).to be instance
34
- expect(subject.query('instance.ssh_key')).to be ssh_key
35
- expect(subject.query(key)).to be value
36
- end
37
-
38
- context 'with a prefix' do
39
- let(:key) { 'name' }
40
- let(:prefix) { '$.instance.ssh_key' }
41
- let(:value) { 'some_name' }
42
- it 'works' do
43
- expect(subject.query(key, prefix)).to be(value)
44
- end
45
- end
46
- end
47
-
48
- context 'querying values that do not exist' do
49
- context 'for a straight key' do
50
- let(:key) { 'missing' }
51
- it 'returns nil' do
52
- expect(subject.query(key)).to be_nil
53
- end
54
- end
55
- context 'for a nested key' do
56
- let(:key) { 'nested.missing' }
57
- it 'returns nil' do
58
- expect(subject.query(key)).to be_nil
59
- end
60
- end
61
- end
62
-
63
- context 'querying collection indices from models' do
64
- let(:instances) { [instance1, instance2] }
65
- let(:instance1) { double('instance1', ssh_key: ssh_key1) }
66
- let(:instance2) { double('instance2', ssh_key: ssh_key2) }
67
- let(:ssh_key1) { double('ssh_key', name: value) }
68
- let(:ssh_key2) { double('ssh_key', name: 'second') }
69
- let(:args) { [path, prefix].compact }
70
-
71
- before { subject.register('instances', instances) }
72
-
73
- it 'resolves the index to the correct member of the collection' do
74
- expect(subject.query('instances')).to be instances
75
- expect(subject.query('instances.at(1).ssh_key')).to be ssh_key2
76
- expect(subject.query('instances.at(0).ssh_key.name')).to be value
77
- end
78
-
79
- it 'returns nil for index out of range' do
80
- expect(subject.query('instances.at(2)')).to be(nil)
81
- expect(subject.query('instances.at(-1)')).to be(nil)
82
- end
83
-
84
- context 'with a prefix' do
85
- let(:key) { 'name' }
86
- let(:prefix) { '$.instances.at(0).ssh_key' }
87
- let(:value) { 'some_name' }
88
-
89
- it 'resolves the index to the correct member of the collection' do
90
- expect(subject.query(key, prefix)).to be(value)
91
- end
92
- end
93
- end
94
-
95
- context 'checking attribute conditions' do
96
- let(:key) { 'instance.ssh_key.name' }
97
- let(:ssh_key) { double('ssh_key', name: value) }
98
- let(:instance_id) { 123 }
99
- let(:instance) { double('instance', ssh_key: ssh_key, id: instance_id) }
100
-
101
- let(:context) { '$' }
102
-
103
- before { subject.register('instance', instance) }
104
-
105
- let(:present_key) { key }
106
- let(:missing_key) { 'instance.ssh_key.something_else' }
107
-
108
- context 'with no condition' do
109
- let(:condition) { nil }
110
- before { expect(ssh_key).to receive(:something_else).and_return(nil) }
111
- it 'works' do
112
- expect(subject.check(context, present_key, condition)).to be true
113
- expect(subject.check(context, missing_key, condition)).to be false
114
- end
115
- end
116
-
117
- context 'with a string condition' do
118
- let(:passing_condition) { value }
119
- let(:failing_condition) { /\w+/.gen }
120
-
121
- it 'works' do
122
- expect(subject.check(context, key, passing_condition)).to be true
123
- expect(subject.check(context, key, failing_condition)).to be false
124
- end
125
- end
126
-
127
- context 'with a regex condition' do
128
- let(:passing_condition) { /\w+/ }
129
- let(:failing_condition) { /\d+/ }
130
-
131
- it 'works' do
132
- expect(subject.check(context, key, passing_condition)).to be true
133
- expect(subject.check(context, key, failing_condition)).to be false
134
- end
135
- end
136
-
137
- context 'with an integer condition' do
138
- let(:key) { 'instance.id' }
139
- let(:passing_condition) { instance_id }
140
- let(:failing_condition) { /\w+/.gen }
141
-
142
- it 'works' do
143
- expect(subject.check(context, key, passing_condition)).to be true
144
- expect(subject.check(context, key, failing_condition)).to be false
145
- end
146
- end
147
-
148
- skip 'with a hash condition' do
149
- end
150
-
151
- context 'with a proc condition' do
152
- let(:passing_condition) { proc { |test_value| test_value == value } }
153
- let(:failing_condition) { proc { |test_value| test_value != value } }
154
-
155
- it 'works' do
156
- expect(subject.check(context, key, passing_condition)).to eq(true)
157
- expect(subject.check(context, key, failing_condition)).to eq(false)
158
- end
159
- end
160
-
161
- context 'with an unsupported condition type' do
162
- let(:condition) { double('weird condition type') }
163
- it 'raises an error' do
164
- expect { subject.check(context, present_key, condition) }.to raise_error(Attributor::AttributorException)
165
- end
166
- end
167
-
168
- context 'with a condition that asserts something IS nil' do
169
- let(:ssh_key) { double('ssh_key', name: nil) }
170
- it 'can be done using the almighty Proc' do
171
- cond = proc { |value| !value.nil? }
172
- expect(subject.check(context, key, cond)).to be false
173
- end
174
- end
175
-
176
- context 'with a relative path' do
177
- let(:context) { '$.instance.ssh_key' }
178
- let(:key) { 'name' }
179
-
180
- it 'works' do
181
- expect(subject.check(context, key, value)).to be true
182
- end
183
- end
184
- end
185
-
186
- # context 'with context stuff...' do
187
-
188
- # let(:ssh_key) { double("ssh_key", name:value) }
189
- # let(:instance) { double("instance", ssh_key:ssh_key) }
190
-
191
- # let(:key) { "ssh_key.name" }
192
- # let(:key) { "$.payload" }
193
- # let(:key) { "ssh_key.name" } # no $ == current object
194
- # let(:key) { "@.ssh_key" } # @ is current object
195
-
196
- # before { subject.register('instance', instance) }
197
-
198
- # it 'works?' do
199
- # # check dependency for 'instance'
200
- # resolver.with 'instance' do |res|
201
- # res.check(key)
202
- # '$.payload'
203
- # end
204
-
205
- # end
206
-
207
- # end
208
-
209
- # context 'integration with attributes that have sub-attributes' do
210
- # when you start to parse... do you set the root in the resolver?
211
- # end
212
- #
213
- # context 'actually using the thing' do
214
-
215
- # # we'll always want to add... right? never really remove?
216
- # # at least not remove for the duration of a given resolver...
217
- # # which will last for one request.
218
- # #
219
- # # could the resolver be an identity-map of sorts for the request?
220
- # # how much overlap is there in there?
221
- # #
222
- # #
223
-
224
- # it 'is really actually quite useful' do
225
- # #attribute = Attributor::Attribute.new ::String, required_if: { "instance.ssh_key.name" : Proc.new { |value| value.nil? } }
226
-
227
- # resolver = Attributor::AttributeResolver.new
228
-
229
- # resolver.register '$.parsed_params', parsed_params
230
- # resolver.register '$.payload', payload
231
-
232
- # resolver.query '$.parsed_params.account_id'
233
-
234
- # end
235
-
236
- # end
237
- end