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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/.travis.yml +6 -4
  4. data/CHANGELOG.md +6 -1
  5. data/Gemfile +1 -1
  6. data/Guardfile +14 -8
  7. data/Rakefile +4 -5
  8. data/attributor.gemspec +34 -29
  9. data/lib/attributor.rb +23 -29
  10. data/lib/attributor/attribute.rb +108 -127
  11. data/lib/attributor/attribute_resolver.rb +12 -26
  12. data/lib/attributor/dsl_compiler.rb +17 -21
  13. data/lib/attributor/dumpable.rb +1 -2
  14. data/lib/attributor/example_mixin.rb +5 -8
  15. data/lib/attributor/exceptions.rb +5 -6
  16. data/lib/attributor/extensions/randexp.rb +3 -5
  17. data/lib/attributor/extras/field_selector.rb +4 -4
  18. data/lib/attributor/extras/field_selector/transformer.rb +6 -7
  19. data/lib/attributor/families/numeric.rb +0 -2
  20. data/lib/attributor/families/temporal.rb +1 -4
  21. data/lib/attributor/hash_dsl_compiler.rb +22 -25
  22. data/lib/attributor/type.rb +24 -32
  23. data/lib/attributor/types/bigdecimal.rb +7 -14
  24. data/lib/attributor/types/boolean.rb +5 -8
  25. data/lib/attributor/types/class.rb +9 -10
  26. data/lib/attributor/types/collection.rb +34 -44
  27. data/lib/attributor/types/container.rb +9 -15
  28. data/lib/attributor/types/csv.rb +7 -10
  29. data/lib/attributor/types/date.rb +20 -25
  30. data/lib/attributor/types/date_time.rb +7 -14
  31. data/lib/attributor/types/float.rb +4 -6
  32. data/lib/attributor/types/hash.rb +171 -196
  33. data/lib/attributor/types/ids.rb +2 -6
  34. data/lib/attributor/types/integer.rb +12 -17
  35. data/lib/attributor/types/model.rb +39 -48
  36. data/lib/attributor/types/object.rb +2 -4
  37. data/lib/attributor/types/polymorphic.rb +118 -0
  38. data/lib/attributor/types/regexp.rb +4 -5
  39. data/lib/attributor/types/string.rb +6 -7
  40. data/lib/attributor/types/struct.rb +8 -15
  41. data/lib/attributor/types/symbol.rb +3 -6
  42. data/lib/attributor/types/tempfile.rb +5 -6
  43. data/lib/attributor/types/time.rb +11 -11
  44. data/lib/attributor/types/uri.rb +9 -10
  45. data/lib/attributor/version.rb +1 -1
  46. data/spec/attribute_resolver_spec.rb +57 -78
  47. data/spec/attribute_spec.rb +174 -216
  48. data/spec/attributor_spec.rb +11 -15
  49. data/spec/dsl_compiler_spec.rb +19 -33
  50. data/spec/dumpable_spec.rb +6 -7
  51. data/spec/extras/field_selector/field_selector_spec.rb +1 -1
  52. data/spec/families_spec.rb +1 -3
  53. data/spec/hash_dsl_compiler_spec.rb +65 -74
  54. data/spec/spec_helper.rb +9 -3
  55. data/spec/support/hashes.rb +2 -3
  56. data/spec/support/models.rb +30 -36
  57. data/spec/support/polymorphics.rb +10 -0
  58. data/spec/type_spec.rb +38 -61
  59. data/spec/types/bigdecimal_spec.rb +11 -15
  60. data/spec/types/boolean_spec.rb +12 -39
  61. data/spec/types/class_spec.rb +10 -11
  62. data/spec/types/collection_spec.rb +72 -81
  63. data/spec/types/container_spec.rb +22 -26
  64. data/spec/types/csv_spec.rb +15 -16
  65. data/spec/types/date_spec.rb +16 -33
  66. data/spec/types/date_time_spec.rb +16 -33
  67. data/spec/types/file_upload_spec.rb +1 -2
  68. data/spec/types/float_spec.rb +7 -14
  69. data/spec/types/hash_spec.rb +285 -289
  70. data/spec/types/ids_spec.rb +5 -7
  71. data/spec/types/integer_spec.rb +37 -46
  72. data/spec/types/model_spec.rb +111 -128
  73. data/spec/types/polymorphic_spec.rb +134 -0
  74. data/spec/types/regexp_spec.rb +4 -7
  75. data/spec/types/string_spec.rb +17 -21
  76. data/spec/types/struct_spec.rb +40 -47
  77. data/spec/types/tempfile_spec.rb +1 -2
  78. data/spec/types/temporal_spec.rb +9 -0
  79. data/spec/types/time_spec.rb +16 -32
  80. data/spec/types/type_spec.rb +15 -0
  81. data/spec/types/uri_spec.rb +6 -7
  82. metadata +77 -25
@@ -3,12 +3,12 @@ module Attributor
3
3
  include Type
4
4
 
5
5
  def self.native_type
6
- return ::String
6
+ ::String
7
7
  end
8
8
 
9
- def self.load(value,context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
10
- if value.kind_of?(Enumerable)
11
- raise IncompatibleTypeError, context: context, value_type: value.class, type: self
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(context=nil, options:{})
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' % [ options[:regexp].inspect, e.message]
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 |key, oldval, newval|
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 ==(other_object)
48
- return false if other_object == nil || !other_object.respond_to?(:attributes)
49
- self.attributes == other_object.attributes
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
- return ::Symbol
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(context=nil, options:{})
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
- return ::Tempfile
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 /[:sentence:]/.gen
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, **opts)
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
- return ::Time
8
+ ::Time
10
9
  end
11
10
 
12
- def self.example(context=nil, options: {})
13
- return self.load(/[:time:]/.gen, context)
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, **options)
17
- return value if value.is_a?(self.native_type)
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 => e
29
- raise Attributor::DeserializationError, context: context, from: value.class, encoding: "Time" , value: value
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
@@ -19,17 +19,17 @@ module Attributor
19
19
  end
20
20
 
21
21
  def self.native_type
22
- return ::URI::Generic
22
+ ::URI::Generic
23
23
  end
24
24
 
25
- def self.example(context=nil, options={})
26
- URI(/[:uri:]/.gen)
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, **options)
29
+ def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
30
30
  return nil if value.nil?
31
31
  case value
32
- when self.native_type
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, **opts)
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.new("Value for option :path is not a Regexp object. Got (#{definition.inspect})")
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 ** 9)}"
72
+ "http://example.com/#{word}/#{rand(10**9)}"
74
73
  end
75
74
  end
@@ -1,3 +1,3 @@
1
1
  module Attributor
2
- VERSION = '5.0.2'
2
+ VERSION = '5.1.0'.freeze
3
3
  end
@@ -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) { "string_value" }
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).should be value
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(:two => value) }
19
- let(:key) { "one.two" }
20
- before { subject.register("one", one) }
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).should be value
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("instance", :ssh_key => ssh_key) }
30
- let(:ssh_key) { double("ssh_key", :name => value) }
31
- let(:key) { "instance.ssh_key.name" }
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("instance").should be instance
37
- subject.query("instance.ssh_key").should be ssh_key
38
- subject.query(key).should be value
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) { "name" }
44
- let(:prefix) { "$.instance.ssh_key"}
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).should be(value)
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) { "missing" }
50
+ let(:key) { 'missing' }
57
51
  it 'returns nil' do
58
- subject.query(key).should be_nil
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) { "nested.missing" }
56
+ let(:key) { 'nested.missing' }
63
57
  it 'returns nil' do
64
- subject.query(key).should be_nil
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', :ssh_key => ssh_key1) }
72
- let(:instance2) { double('instance2', :ssh_key => ssh_key2) }
73
- let(:ssh_key1) { double('ssh_key', :name => value) }
74
- let(:ssh_key2) { double('ssh_key', :name => 'second') }
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').should be instances
81
- subject.query('instances.at(1).ssh_key').should be ssh_key2
82
- subject.query('instances.at(0).ssh_key.name').should be value
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)').should be(nil)
87
- subject.query('instances.at(-1)').should be(nil)
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).should be(value)
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) { "instance.ssh_key.name" }
103
- let(:ssh_key) { double("ssh_key", :name => value) }
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("instance", ssh_key: ssh_key, id: instance_id) }
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.should_receive(:something_else).and_return(nil) }
110
+ before { expect(ssh_key).to receive(:something_else).and_return(nil) }
117
111
  it 'works' do
118
- subject.check(context, present_key, condition).should be true
119
- subject.check(context, missing_key, condition).should be false
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).should be true
130
- subject.check(context, key, failing_condition).should be false
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).should be true
141
- subject.check(context, key, failing_condition).should be false
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) { "instance.id" }
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).should be true
153
- subject.check(context, key, failing_condition).should be false
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
- pending 'with a hash condition' do
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) { Proc.new { |test_value| test_value == value } }
162
- let(:failing_condition) { Proc.new { |test_value| test_value != value } }
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("weird condition type") }
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("ssh_key", :name => nil) }
169
+ let(:ssh_key) { double('ssh_key', name: nil) }
180
170
  it 'can be done using the almighty Proc' do
181
- cond = Proc.new { |value| !value.nil? }
182
- subject.check(context, key, cond).should be false
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) { "$.instance.ssh_key"}
188
- let(:key) { "name" }
177
+ let(:context) { '$.instance.ssh_key' }
178
+ let(:key) { 'name' }
189
179
 
190
180
  it 'works' do
191
- subject.check(context, key, value).should be true
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
-