attributor 5.0.2 → 5.1.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/.rubocop.yml +30 -0
- data/.travis.yml +6 -4
- data/CHANGELOG.md +6 -1
- data/Gemfile +1 -1
- data/Guardfile +14 -8
- data/Rakefile +4 -5
- data/attributor.gemspec +34 -29
- data/lib/attributor.rb +23 -29
- data/lib/attributor/attribute.rb +108 -127
- data/lib/attributor/attribute_resolver.rb +12 -26
- data/lib/attributor/dsl_compiler.rb +17 -21
- data/lib/attributor/dumpable.rb +1 -2
- data/lib/attributor/example_mixin.rb +5 -8
- data/lib/attributor/exceptions.rb +5 -6
- data/lib/attributor/extensions/randexp.rb +3 -5
- data/lib/attributor/extras/field_selector.rb +4 -4
- data/lib/attributor/extras/field_selector/transformer.rb +6 -7
- data/lib/attributor/families/numeric.rb +0 -2
- data/lib/attributor/families/temporal.rb +1 -4
- data/lib/attributor/hash_dsl_compiler.rb +22 -25
- data/lib/attributor/type.rb +24 -32
- data/lib/attributor/types/bigdecimal.rb +7 -14
- data/lib/attributor/types/boolean.rb +5 -8
- data/lib/attributor/types/class.rb +9 -10
- data/lib/attributor/types/collection.rb +34 -44
- data/lib/attributor/types/container.rb +9 -15
- data/lib/attributor/types/csv.rb +7 -10
- data/lib/attributor/types/date.rb +20 -25
- data/lib/attributor/types/date_time.rb +7 -14
- data/lib/attributor/types/float.rb +4 -6
- data/lib/attributor/types/hash.rb +171 -196
- data/lib/attributor/types/ids.rb +2 -6
- data/lib/attributor/types/integer.rb +12 -17
- data/lib/attributor/types/model.rb +39 -48
- data/lib/attributor/types/object.rb +2 -4
- data/lib/attributor/types/polymorphic.rb +118 -0
- data/lib/attributor/types/regexp.rb +4 -5
- data/lib/attributor/types/string.rb +6 -7
- data/lib/attributor/types/struct.rb +8 -15
- data/lib/attributor/types/symbol.rb +3 -6
- data/lib/attributor/types/tempfile.rb +5 -6
- data/lib/attributor/types/time.rb +11 -11
- data/lib/attributor/types/uri.rb +9 -10
- data/lib/attributor/version.rb +1 -1
- data/spec/attribute_resolver_spec.rb +57 -78
- data/spec/attribute_spec.rb +174 -216
- data/spec/attributor_spec.rb +11 -15
- data/spec/dsl_compiler_spec.rb +19 -33
- data/spec/dumpable_spec.rb +6 -7
- data/spec/extras/field_selector/field_selector_spec.rb +1 -1
- data/spec/families_spec.rb +1 -3
- data/spec/hash_dsl_compiler_spec.rb +65 -74
- data/spec/spec_helper.rb +9 -3
- data/spec/support/hashes.rb +2 -3
- data/spec/support/models.rb +30 -36
- data/spec/support/polymorphics.rb +10 -0
- data/spec/type_spec.rb +38 -61
- data/spec/types/bigdecimal_spec.rb +11 -15
- data/spec/types/boolean_spec.rb +12 -39
- data/spec/types/class_spec.rb +10 -11
- data/spec/types/collection_spec.rb +72 -81
- data/spec/types/container_spec.rb +22 -26
- data/spec/types/csv_spec.rb +15 -16
- data/spec/types/date_spec.rb +16 -33
- data/spec/types/date_time_spec.rb +16 -33
- data/spec/types/file_upload_spec.rb +1 -2
- data/spec/types/float_spec.rb +7 -14
- data/spec/types/hash_spec.rb +285 -289
- data/spec/types/ids_spec.rb +5 -7
- data/spec/types/integer_spec.rb +37 -46
- data/spec/types/model_spec.rb +111 -128
- data/spec/types/polymorphic_spec.rb +134 -0
- data/spec/types/regexp_spec.rb +4 -7
- data/spec/types/string_spec.rb +17 -21
- data/spec/types/struct_spec.rb +40 -47
- data/spec/types/tempfile_spec.rb +1 -2
- data/spec/types/temporal_spec.rb +9 -0
- data/spec/types/time_spec.rb +16 -32
- data/spec/types/type_spec.rb +15 -0
- data/spec/types/uri_spec.rb +6 -7
- metadata +77 -25
@@ -3,12 +3,12 @@ module Attributor
|
|
3
3
|
include Type
|
4
4
|
|
5
5
|
def self.native_type
|
6
|
-
|
6
|
+
::String
|
7
7
|
end
|
8
8
|
|
9
|
-
def self.load(value,context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
10
|
-
if value.
|
11
|
-
raise IncompatibleTypeError,
|
9
|
+
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
10
|
+
if value.is_a?(Enumerable)
|
11
|
+
raise IncompatibleTypeError, context: context, value_type: value.class, type: self
|
12
12
|
end
|
13
13
|
|
14
14
|
value && String(value)
|
@@ -16,13 +16,13 @@ module Attributor
|
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.example(
|
19
|
+
def self.example(_context = nil, options: {})
|
20
20
|
if options[:regexp]
|
21
21
|
begin
|
22
22
|
# It may fail to generate an example, see bug #72.
|
23
23
|
options[:regexp].gen
|
24
24
|
rescue => e
|
25
|
-
'Failed to generate example for %s : %s'
|
25
|
+
format('Failed to generate example for %s : %s', options[:regexp].inspect, e.message)
|
26
26
|
end
|
27
27
|
else
|
28
28
|
/\w+/.gen
|
@@ -32,6 +32,5 @@ module Attributor
|
|
32
32
|
def self.family
|
33
33
|
'string'
|
34
34
|
end
|
35
|
-
|
36
35
|
end
|
37
36
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
|
2
2
|
module Attributor
|
3
3
|
class Struct < Attributor::Model
|
4
|
-
|
5
4
|
def self.constructable?
|
6
5
|
true
|
7
6
|
end
|
8
7
|
|
9
8
|
# Construct a new subclass, using attribute_definition to define attributes.
|
10
|
-
def self.construct(attribute_definition, options={})
|
9
|
+
def self.construct(attribute_definition, options = {})
|
11
10
|
# if we're in a subclass of Struct, but not attribute_definition is provided, we're
|
12
11
|
# not REALLY trying to define a new struct. more than likely Collection is calling
|
13
12
|
# construct on us.
|
@@ -21,7 +20,7 @@ module Attributor
|
|
21
20
|
return self if attribute_definition.nil?
|
22
21
|
|
23
22
|
if options[:reference]
|
24
|
-
options.merge!(options[:reference].options) do |
|
23
|
+
options.merge!(options[:reference].options) do |_key, oldval, _newval|
|
25
24
|
oldval
|
26
25
|
end
|
27
26
|
end
|
@@ -29,25 +28,19 @@ module Attributor
|
|
29
28
|
::Class.new(self) do
|
30
29
|
attributes options, &attribute_definition
|
31
30
|
end
|
32
|
-
|
33
31
|
end
|
34
32
|
|
35
|
-
|
36
33
|
def self.definition
|
37
34
|
# Could probably do this better, but its use should be memoized in the enclosing Attribute
|
38
|
-
if self == Attributor::Struct
|
39
|
-
raise AttributorException, "Can not use a pure Struct without defining sub-attributes"
|
40
|
-
else
|
41
|
-
super
|
42
|
-
end
|
43
|
-
end
|
35
|
+
raise AttributorException, 'Can not use a pure Struct without defining sub-attributes' if self == Attributor::Struct
|
44
36
|
|
37
|
+
super
|
38
|
+
end
|
45
39
|
|
46
40
|
# Two structs are equal if their attributes are equal
|
47
|
-
def ==(
|
48
|
-
return false if
|
49
|
-
|
41
|
+
def ==(other)
|
42
|
+
return false if other.nil? || !other.respond_to?(:attributes)
|
43
|
+
attributes == other.attributes
|
50
44
|
end
|
51
|
-
|
52
45
|
end
|
53
46
|
end
|
@@ -3,24 +3,21 @@ module Attributor
|
|
3
3
|
include Type
|
4
4
|
|
5
5
|
def self.native_type
|
6
|
-
|
6
|
+
::Symbol
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
def self.load(value,context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
9
|
+
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
11
10
|
value.to_sym
|
12
11
|
rescue
|
13
12
|
super
|
14
13
|
end
|
15
14
|
|
16
|
-
def self.example(
|
15
|
+
def self.example(_context = nil, options: {})
|
17
16
|
:example
|
18
17
|
end
|
19
18
|
|
20
19
|
def self.family
|
21
20
|
String.family
|
22
21
|
end
|
23
|
-
|
24
22
|
end
|
25
|
-
|
26
23
|
end
|
@@ -5,22 +5,22 @@ module Attributor
|
|
5
5
|
include Attributor::Type
|
6
6
|
|
7
7
|
def self.native_type
|
8
|
-
|
8
|
+
::Tempfile
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.example(context=Attributor::DEFAULT_ROOT_CONTEXT, options:{})
|
11
|
+
def self.example(context = Attributor::DEFAULT_ROOT_CONTEXT, options: {})
|
12
12
|
file = ::Tempfile.new(Attributor.humanize_context(context))
|
13
|
-
file.write
|
13
|
+
file.write Randgen.sentence
|
14
14
|
file.write '.'
|
15
15
|
file.rewind
|
16
16
|
file
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.dump(value, **
|
19
|
+
def self.dump(value, **_opts)
|
20
20
|
value && value.read
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.load(value,context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
23
|
+
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **options)
|
24
24
|
# TODO: handle additional cases that make sense
|
25
25
|
case value
|
26
26
|
when ::String
|
@@ -38,6 +38,5 @@ module Attributor
|
|
38
38
|
def self.family
|
39
39
|
String.family
|
40
40
|
end
|
41
|
-
|
42
41
|
end
|
43
42
|
end
|
@@ -1,39 +1,39 @@
|
|
1
1
|
require 'date'
|
2
2
|
|
3
3
|
module Attributor
|
4
|
-
|
5
4
|
class Time < Temporal
|
6
5
|
include Type
|
7
6
|
|
8
7
|
def self.native_type
|
9
|
-
|
8
|
+
::Time
|
10
9
|
end
|
11
10
|
|
12
|
-
def self.example(context=nil, options: {})
|
13
|
-
|
11
|
+
def self.example(context = nil, options: {})
|
12
|
+
load(Randgen.time, context)
|
14
13
|
end
|
15
14
|
|
16
|
-
def self.load(value,context=Attributor::DEFAULT_ROOT_CONTEXT, **
|
17
|
-
return value if value.is_a?(
|
15
|
+
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
16
|
+
return value if value.is_a?(native_type)
|
18
17
|
return nil if value.nil?
|
19
18
|
|
20
19
|
return value.to_time if value.respond_to?(:to_time)
|
21
20
|
|
21
|
+
self.parse(value, context)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse(value, context)
|
22
25
|
case value
|
23
26
|
when ::Integer
|
24
27
|
return ::Time.at(value)
|
25
28
|
when ::String
|
26
29
|
begin
|
27
30
|
return ::Time.parse(value)
|
28
|
-
rescue ArgumentError
|
29
|
-
raise Attributor::DeserializationError, context: context, from: value.class, encoding:
|
31
|
+
rescue ArgumentError
|
32
|
+
raise Attributor::DeserializationError, context: context, from: value.class, encoding: 'Time', value: value
|
30
33
|
end
|
31
34
|
else
|
32
35
|
raise CoercionError, context: context, from: value.class, to: self, value: value
|
33
36
|
end
|
34
37
|
end
|
35
|
-
|
36
|
-
|
37
38
|
end
|
38
|
-
|
39
39
|
end
|
data/lib/attributor/types/uri.rb
CHANGED
@@ -19,17 +19,17 @@ module Attributor
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.native_type
|
22
|
-
|
22
|
+
::URI::Generic
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.example(
|
26
|
-
URI(
|
25
|
+
def self.example(_context = nil, options: {})
|
26
|
+
URI(Randgen.uri)
|
27
27
|
end
|
28
28
|
|
29
|
-
def self.load(value, context=Attributor::DEFAULT_ROOT_CONTEXT, **
|
29
|
+
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
30
30
|
return nil if value.nil?
|
31
31
|
case value
|
32
|
-
when
|
32
|
+
when native_type
|
33
33
|
value
|
34
34
|
when ::String
|
35
35
|
URI(value)
|
@@ -38,11 +38,11 @@ module Attributor
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def self.dump(value, **
|
41
|
+
def self.dump(value, **_opts)
|
42
42
|
value.to_s
|
43
43
|
end
|
44
44
|
|
45
|
-
def self.validate(value,context=Attributor::DEFAULT_ROOT_CONTEXT,attribute)
|
45
|
+
def self.validate(value, context = Attributor::DEFAULT_ROOT_CONTEXT, attribute)
|
46
46
|
errors = []
|
47
47
|
|
48
48
|
if attribute && (definition = attribute.options[:path])
|
@@ -57,19 +57,18 @@ module Attributor
|
|
57
57
|
case name
|
58
58
|
when :path
|
59
59
|
unless definition.is_a? ::Regexp
|
60
|
-
raise AttributorException
|
60
|
+
raise AttributorException, "Value for option :path is not a Regexp object. Got (#{definition.inspect})"
|
61
61
|
end
|
62
62
|
:ok
|
63
63
|
else
|
64
64
|
:unknown
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
71
70
|
class Randgen
|
72
71
|
def self.uri
|
73
|
-
"http://example.com/#{word}/#{rand(10
|
72
|
+
"http://example.com/#{word}/#{rand(10**9)}"
|
74
73
|
end
|
75
74
|
end
|
data/lib/attributor/version.rb
CHANGED
@@ -1,108 +1,102 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
2
|
|
3
|
-
|
4
3
|
describe Attributor::AttributeResolver do
|
5
4
|
let(:value) { /\w+/.gen }
|
6
5
|
|
7
6
|
context 'registering and querying simple values' do
|
8
|
-
let(:name) {
|
9
|
-
before { subject.register(name,value) }
|
7
|
+
let(:name) { 'string_value' }
|
8
|
+
before { subject.register(name, value) }
|
10
9
|
|
11
10
|
it 'works' do
|
12
|
-
subject.query(name).
|
11
|
+
expect(subject.query(name)).to be value
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
15
|
context 'querying and registering nested values' do
|
18
|
-
let(:one) { double(:
|
19
|
-
let(:key) {
|
20
|
-
before { subject.register(
|
16
|
+
let(:one) { double(two: value) }
|
17
|
+
let(:key) { 'one.two' }
|
18
|
+
before { subject.register('one', one) }
|
21
19
|
|
22
20
|
it 'works' do
|
23
|
-
subject.query(key).
|
21
|
+
expect(subject.query(key)).to be value
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
|
-
|
28
25
|
context 'querying nested values from models' do
|
29
|
-
let(:instance) { double(
|
30
|
-
let(:ssh_key) { double(
|
31
|
-
let(:key) {
|
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' }
|
32
29
|
|
33
30
|
before { subject.register('instance', instance) }
|
34
31
|
|
35
32
|
it 'works' do
|
36
|
-
subject.query(
|
37
|
-
subject.query(
|
38
|
-
subject.query(key).
|
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
|
39
36
|
end
|
40
37
|
|
41
|
-
|
42
38
|
context 'with a prefix' do
|
43
|
-
let(:key) {
|
44
|
-
let(:prefix) {
|
39
|
+
let(:key) { 'name' }
|
40
|
+
let(:prefix) { '$.instance.ssh_key' }
|
45
41
|
let(:value) { 'some_name' }
|
46
42
|
it 'works' do
|
47
|
-
subject.query(key,prefix).
|
43
|
+
expect(subject.query(key, prefix)).to be(value)
|
48
44
|
end
|
49
45
|
end
|
50
|
-
|
51
46
|
end
|
52
47
|
|
53
|
-
|
54
48
|
context 'querying values that do not exist' do
|
55
49
|
context 'for a straight key' do
|
56
|
-
let(:key) {
|
50
|
+
let(:key) { 'missing' }
|
57
51
|
it 'returns nil' do
|
58
|
-
subject.query(key).
|
52
|
+
expect(subject.query(key)).to be_nil
|
59
53
|
end
|
60
54
|
end
|
61
55
|
context 'for a nested key' do
|
62
|
-
let(:key) {
|
56
|
+
let(:key) { 'nested.missing' }
|
63
57
|
it 'returns nil' do
|
64
|
-
subject.query(key).
|
58
|
+
expect(subject.query(key)).to be_nil
|
65
59
|
end
|
66
60
|
end
|
67
61
|
end
|
68
62
|
|
69
63
|
context 'querying collection indices from models' do
|
70
64
|
let(:instances) { [instance1, instance2] }
|
71
|
-
let(:instance1) { double('instance1', :
|
72
|
-
let(:instance2) { double('instance2', :
|
73
|
-
let(:ssh_key1) { double('ssh_key', :
|
74
|
-
let(:ssh_key2) { double('ssh_key', :
|
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') }
|
75
69
|
let(:args) { [path, prefix].compact }
|
76
70
|
|
77
71
|
before { subject.register('instances', instances) }
|
78
72
|
|
79
73
|
it 'resolves the index to the correct member of the collection' do
|
80
|
-
subject.query('instances').
|
81
|
-
subject.query('instances.at(1).ssh_key').
|
82
|
-
subject.query('instances.at(0).ssh_key.name').
|
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
|
83
77
|
end
|
84
78
|
|
85
79
|
it 'returns nil for index out of range' do
|
86
|
-
subject.query('instances.at(2)').
|
87
|
-
subject.query('instances.at(-1)').
|
80
|
+
expect(subject.query('instances.at(2)')).to be(nil)
|
81
|
+
expect(subject.query('instances.at(-1)')).to be(nil)
|
88
82
|
end
|
89
83
|
|
90
84
|
context 'with a prefix' do
|
91
85
|
let(:key) { 'name' }
|
92
|
-
let(:prefix) { '$.instances.at(0).ssh_key'}
|
86
|
+
let(:prefix) { '$.instances.at(0).ssh_key' }
|
93
87
|
let(:value) { 'some_name' }
|
94
88
|
|
95
89
|
it 'resolves the index to the correct member of the collection' do
|
96
|
-
subject.query(key, prefix).
|
90
|
+
expect(subject.query(key, prefix)).to be(value)
|
97
91
|
end
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
101
95
|
context 'checking attribute conditions' do
|
102
|
-
let(:key) {
|
103
|
-
let(:ssh_key) { double(
|
96
|
+
let(:key) { 'instance.ssh_key.name' }
|
97
|
+
let(:ssh_key) { double('ssh_key', name: value) }
|
104
98
|
let(:instance_id) { 123 }
|
105
|
-
let(:instance) { double(
|
99
|
+
let(:instance) { double('instance', ssh_key: ssh_key, id: instance_id) }
|
106
100
|
|
107
101
|
let(:context) { '$' }
|
108
102
|
|
@@ -113,89 +107,82 @@ describe Attributor::AttributeResolver do
|
|
113
107
|
|
114
108
|
context 'with no condition' do
|
115
109
|
let(:condition) { nil }
|
116
|
-
before { ssh_key.
|
110
|
+
before { expect(ssh_key).to receive(:something_else).and_return(nil) }
|
117
111
|
it 'works' do
|
118
|
-
subject.check(context, present_key, condition).
|
119
|
-
subject.check(context, missing_key, condition).
|
112
|
+
expect(subject.check(context, present_key, condition)).to be true
|
113
|
+
expect(subject.check(context, missing_key, condition)).to be false
|
120
114
|
end
|
121
115
|
end
|
122
116
|
|
123
|
-
|
124
117
|
context 'with a string condition' do
|
125
118
|
let(:passing_condition) { value }
|
126
119
|
let(:failing_condition) { /\w+/.gen }
|
127
120
|
|
128
121
|
it 'works' do
|
129
|
-
subject.check(context, key, passing_condition).
|
130
|
-
subject.check(context, key, failing_condition).
|
122
|
+
expect(subject.check(context, key, passing_condition)).to be true
|
123
|
+
expect(subject.check(context, key, failing_condition)).to be false
|
131
124
|
end
|
132
125
|
end
|
133
126
|
|
134
|
-
|
135
127
|
context 'with a regex condition' do
|
136
128
|
let(:passing_condition) { /\w+/ }
|
137
129
|
let(:failing_condition) { /\d+/ }
|
138
130
|
|
139
131
|
it 'works' do
|
140
|
-
subject.check(context, key, passing_condition).
|
141
|
-
subject.check(context, key, failing_condition).
|
132
|
+
expect(subject.check(context, key, passing_condition)).to be true
|
133
|
+
expect(subject.check(context, key, failing_condition)).to be false
|
142
134
|
end
|
143
|
-
|
144
135
|
end
|
145
136
|
|
146
137
|
context 'with an integer condition' do
|
147
|
-
let(:key) {
|
138
|
+
let(:key) { 'instance.id' }
|
148
139
|
let(:passing_condition) { instance_id }
|
149
140
|
let(:failing_condition) { /\w+/.gen }
|
150
141
|
|
151
142
|
it 'works' do
|
152
|
-
subject.check(context, key, passing_condition).
|
153
|
-
subject.check(context, key, failing_condition).
|
143
|
+
expect(subject.check(context, key, passing_condition)).to be true
|
144
|
+
expect(subject.check(context, key, failing_condition)).to be false
|
154
145
|
end
|
155
146
|
end
|
156
|
-
|
157
|
-
|
147
|
+
|
148
|
+
skip 'with a hash condition' do
|
158
149
|
end
|
159
150
|
|
160
151
|
context 'with a proc condition' do
|
161
|
-
let(:passing_condition) {
|
162
|
-
let(:failing_condition) {
|
152
|
+
let(:passing_condition) { proc { |test_value| test_value == value } }
|
153
|
+
let(:failing_condition) { proc { |test_value| test_value != value } }
|
163
154
|
|
164
155
|
it 'works' do
|
165
156
|
expect(subject.check(context, key, passing_condition)).to eq(true)
|
166
157
|
expect(subject.check(context, key, failing_condition)).to eq(false)
|
167
158
|
end
|
168
|
-
|
169
159
|
end
|
170
160
|
|
171
161
|
context 'with an unsupported condition type' do
|
172
|
-
let(:condition) { double(
|
162
|
+
let(:condition) { double('weird condition type') }
|
173
163
|
it 'raises an error' do
|
174
|
-
expect { subject.check(context, present_key, condition) }.to raise_error
|
164
|
+
expect { subject.check(context, present_key, condition) }.to raise_error(Attributor::AttributorException)
|
175
165
|
end
|
176
166
|
end
|
177
167
|
|
178
168
|
context 'with a condition that asserts something IS nil' do
|
179
|
-
let(:ssh_key) { double(
|
169
|
+
let(:ssh_key) { double('ssh_key', name: nil) }
|
180
170
|
it 'can be done using the almighty Proc' do
|
181
|
-
cond =
|
182
|
-
subject.check(context, key, cond).
|
171
|
+
cond = proc { |value| !value.nil? }
|
172
|
+
expect(subject.check(context, key, cond)).to be false
|
183
173
|
end
|
184
174
|
end
|
185
175
|
|
186
176
|
context 'with a relative path' do
|
187
|
-
let(:context) {
|
188
|
-
let(:key) {
|
177
|
+
let(:context) { '$.instance.ssh_key' }
|
178
|
+
let(:key) { 'name' }
|
189
179
|
|
190
180
|
it 'works' do
|
191
|
-
subject.check(context, key, value).
|
181
|
+
expect(subject.check(context, key, value)).to be true
|
192
182
|
end
|
193
|
-
|
194
183
|
end
|
195
|
-
|
196
184
|
end
|
197
185
|
|
198
|
-
|
199
186
|
# context 'with context stuff...' do
|
200
187
|
|
201
188
|
# let(:ssh_key) { double("ssh_key", name:value) }
|
@@ -219,14 +206,12 @@ describe Attributor::AttributeResolver do
|
|
219
206
|
|
220
207
|
# end
|
221
208
|
|
222
|
-
|
223
209
|
# context 'integration with attributes that have sub-attributes' do
|
224
|
-
#when you start to parse... do you set the root in the resolver?
|
210
|
+
# when you start to parse... do you set the root in the resolver?
|
225
211
|
# end
|
226
212
|
#
|
227
213
|
# context 'actually using the thing' do
|
228
214
|
|
229
|
-
|
230
215
|
# # we'll always want to add... right? never really remove?
|
231
216
|
# # at least not remove for the duration of a given resolver...
|
232
217
|
# # which will last for one request.
|
@@ -246,13 +231,7 @@ describe Attributor::AttributeResolver do
|
|
246
231
|
|
247
232
|
# resolver.query '$.parsed_params.account_id'
|
248
233
|
|
249
|
-
|
250
234
|
# end
|
251
235
|
|
252
|
-
|
253
236
|
# end
|
254
|
-
|
255
237
|
end
|
256
|
-
|
257
|
-
|
258
|
-
|