attributor 5.0.2 → 5.1.0

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