attributor 5.0.2 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|