arstotzka 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +6 -4
- data/README.md +61 -64
- data/config/yardstick.yml +14 -26
- data/lib/arstotzka/base.rb +27 -0
- data/lib/arstotzka/builder.rb +24 -83
- data/lib/arstotzka/class_methods.rb +3 -3
- data/lib/arstotzka/crawler.rb +33 -29
- data/lib/arstotzka/fetcher.rb +11 -23
- data/lib/arstotzka/options.rb +72 -0
- data/lib/arstotzka/reader.rb +32 -23
- data/lib/arstotzka/type_cast.rb +3 -3
- data/lib/arstotzka/version.rb +1 -1
- data/lib/arstotzka/wrapper.rb +18 -10
- data/lib/arstotzka.rb +4 -2
- data/scripts/check_readme.sh +6 -0
- data/spec/integration/yard/arstotzka/builder_spec.rb +11 -11
- data/spec/integration/yard/arstotzka/crawler_spec.rb +7 -7
- data/spec/integration/yard/arstotzka/fetcher_spec.rb +3 -3
- data/spec/integration/yard/arstotzka/reader_spec.rb +5 -5
- data/spec/integration/yard/arstotzka/wrapper_spec.rb +6 -6
- data/spec/lib/arstotzka/builder_spec.rb +7 -7
- data/spec/lib/arstotzka/crawler_spec.rb +28 -28
- data/spec/lib/arstotzka/fetcher_spec.rb +9 -9
- data/spec/lib/arstotzka/options_spec.rb +208 -0
- data/spec/lib/arstotzka/reader_spec.rb +15 -15
- data/spec/lib/arstotzka/wrapper_spec.rb +13 -13
- data/spec/lib/arstotzka_spec.rb +2 -2
- data/spec/support/models/arstotzka/dummy.rb +4 -4
- data/spec/support/models/collector.rb +3 -1
- data/spec/support/models/star_gazer.rb +1 -1
- metadata +7 -2
data/lib/arstotzka/fetcher.rb
CHANGED
@@ -6,19 +6,19 @@ module Arstotzka
|
|
6
6
|
# Class responsible for orquestrating the fetch value from the hash
|
7
7
|
# and post-processing it
|
8
8
|
class Fetcher
|
9
|
-
include
|
9
|
+
include Base
|
10
10
|
|
11
11
|
# Creates an instance of Artotzka::Fetcher
|
12
12
|
#
|
13
13
|
# @param hash [Hash] Hash to be crawled for value
|
14
14
|
# @param instance [Object] object whose methods will be called after for processing
|
15
|
-
# @param
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
# @param options_hash [Hash] options that will be passed to {Crawler}, {Wrapper} and {Reader}
|
16
|
+
def initialize(hash, instance, options_hash = {})
|
17
|
+
self.options = options_hash
|
18
|
+
|
19
|
+
@keys = options.path.to_s.split('.')
|
19
20
|
@hash = hash
|
20
21
|
@instance = instance
|
21
|
-
@options = options
|
22
22
|
end
|
23
23
|
|
24
24
|
# Crawls the hash for the value
|
@@ -64,7 +64,7 @@ module Arstotzka
|
|
64
64
|
# instance = Account.new
|
65
65
|
# fetcher = Arstotzka::Fetcher.new(hash, instance,
|
66
66
|
# path: 'transactions',
|
67
|
-
#
|
67
|
+
# klass: Transaction,
|
68
68
|
# after: :filter_income
|
69
69
|
# )
|
70
70
|
#
|
@@ -82,9 +82,8 @@ module Arstotzka
|
|
82
82
|
private
|
83
83
|
|
84
84
|
# @private
|
85
|
-
attr_reader :
|
86
|
-
|
87
|
-
delegate :after, :flatten, to: :options_object
|
85
|
+
attr_reader :keys, :hash, :instance, :options
|
86
|
+
delegate :after, :flatten, to: :options
|
88
87
|
delegate :wrap, to: :wrapper
|
89
88
|
|
90
89
|
# @private
|
@@ -110,7 +109,7 @@ module Arstotzka
|
|
110
109
|
#
|
111
110
|
# @see #crawler
|
112
111
|
def crawler_options
|
113
|
-
options.
|
112
|
+
options.merge(keys: keys)
|
114
113
|
end
|
115
114
|
|
116
115
|
# @private
|
@@ -119,18 +118,7 @@ module Arstotzka
|
|
119
118
|
#
|
120
119
|
# @return [Arstotzka::Wrapper] the wrapper
|
121
120
|
def wrapper
|
122
|
-
@wrapper ||= Arstotzka::Wrapper.new(
|
123
|
-
end
|
124
|
-
|
125
|
-
# @private
|
126
|
-
#
|
127
|
-
# Hash for wrapper initialization
|
128
|
-
#
|
129
|
-
# @return [Hash]
|
130
|
-
#
|
131
|
-
# @see #wrapper
|
132
|
-
def wrapper_options
|
133
|
-
options.slice(:clazz, :type)
|
121
|
+
@wrapper ||= Arstotzka::Wrapper.new(options)
|
134
122
|
end
|
135
123
|
end
|
136
124
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arstotzka
|
4
|
+
# @api private
|
5
|
+
#
|
6
|
+
# Class responsible to hold the options
|
7
|
+
class Options < ::OpenStruct
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
json: :json,
|
10
|
+
path: nil,
|
11
|
+
full_path: nil,
|
12
|
+
cached: false,
|
13
|
+
after: false,
|
14
|
+
case: :lower_camel,
|
15
|
+
klass: nil,
|
16
|
+
compact: false,
|
17
|
+
default: nil,
|
18
|
+
flatten: false,
|
19
|
+
type: :none
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
# Creates a new instance of Options
|
23
|
+
#
|
24
|
+
# @param options [Hash] options hash
|
25
|
+
# Options hash will be merged with {DEFAULT_OPTIONS}
|
26
|
+
# @option options [Class] klass class to receive the methods
|
27
|
+
# @option options [String/Symbol] path path of hash attributes to find the root
|
28
|
+
# where the attribute live (then fetching it using the attribute name)
|
29
|
+
# @option options [String/Symbol] full_path: path of hash attributes to find exacttly where the
|
30
|
+
# value live (ignoring the attribute name)
|
31
|
+
# @option options [String/Symbol] json: name of the method containing the hash to be crawled
|
32
|
+
# @option options [Boolean] cached: flag if the result should be memorized instead of repeating
|
33
|
+
# the crawling
|
34
|
+
# @option options [String/Symbol] case: {Reader} flag definining on which case will
|
35
|
+
# the keys be defined
|
36
|
+
# - lower_camel: keys in the hash are lowerCamelCase
|
37
|
+
# - upper_camel: keys in the hash are UpperCamelCase
|
38
|
+
# - snake: keys in the hash are snake_case
|
39
|
+
# @option options [Boolean] compact: {Crawler} flag to apply Array#compact thus
|
40
|
+
# removing nil results
|
41
|
+
# @option options [Class] klass: {Fetcher} option thatwhen passed, wraps the result in an
|
42
|
+
# instance of the given class
|
43
|
+
# @option options [String/Symbol] after: {Fetcher} option with the name of the method to be
|
44
|
+
# called once the value is fetched for mapping the value
|
45
|
+
# @option options [Boolean] flatten: {Fetcher} flag to aplly Array#flatten thus
|
46
|
+
# avoing nested arrays
|
47
|
+
# @option options [String/Symbol] type: {Fetcher} option declaring the type of the returned
|
48
|
+
# value (to use casting)
|
49
|
+
# - integer
|
50
|
+
# - string
|
51
|
+
# - float
|
52
|
+
#
|
53
|
+
# @see Arstotzka::Options::DEFAULT_OPTIONS
|
54
|
+
# @return [Arstotzka::Options]
|
55
|
+
def initialize(options)
|
56
|
+
klass = options.delete(:class)
|
57
|
+
warn ":class has been deprecated, prefer 'expose klass: #{klass}'" if klass
|
58
|
+
options[:klass] ||= klass
|
59
|
+
|
60
|
+
super(DEFAULT_OPTIONS.merge(options))
|
61
|
+
end
|
62
|
+
|
63
|
+
# @private
|
64
|
+
#
|
65
|
+
# Creates a new instance mergin the given hash with @options
|
66
|
+
#
|
67
|
+
# @return Arstotzka::Options
|
68
|
+
def merge(options)
|
69
|
+
self.class.new(to_h.merge(options))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/arstotzka/reader.rb
CHANGED
@@ -3,26 +3,33 @@
|
|
3
3
|
module Arstotzka
|
4
4
|
# @api private
|
5
5
|
#
|
6
|
-
# Reads a value from a hash using the
|
6
|
+
# Reads a value from a hash using the keys as list of keys
|
7
7
|
class Reader
|
8
|
+
include Base
|
9
|
+
|
8
10
|
# Creates a new instance of Reader
|
9
11
|
#
|
10
|
-
# @
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
# @overload initialize(options_hash={})
|
13
|
+
# @param options_hash [Hash] options of initialization
|
14
|
+
# @option options_hash keys [Array] keys of keys broken down as array
|
15
|
+
# @option options_hash case [Symbol] Case of the keys
|
16
|
+
# - lower_camel: keys in the hash are lowerCamelCase
|
17
|
+
# - upper_camel: keys in the hash are UpperCamelCase
|
18
|
+
# - snake: keys in the hash are snake_case
|
19
|
+
# @overload initialize(options)
|
20
|
+
# @param options [Arstotzka::Options] options of initialization object
|
21
|
+
#
|
22
|
+
# @return [Arstotzka::Reader]
|
23
|
+
def initialize(options_hash = {})
|
24
|
+
self.options = options_hash
|
25
|
+
|
26
|
+
@keys = options.keys.map(&method(:change_case))
|
20
27
|
end
|
21
28
|
|
22
29
|
# Reads the value of one key in the hash
|
23
30
|
#
|
24
31
|
# @param hash [Hash] hash to be read
|
25
|
-
# @param index [Integer] Index of the key (in
|
32
|
+
# @param index [Integer] Index of the key (in keys) to be used
|
26
33
|
#
|
27
34
|
# @return [Object] The value fetched from the hash
|
28
35
|
#
|
@@ -36,25 +43,25 @@ module Arstotzka
|
|
36
43
|
# ]
|
37
44
|
# }
|
38
45
|
#
|
39
|
-
# reader = Arstotzka::Reader.new(%w(person full_name),
|
46
|
+
# reader = Arstotzka::Reader.new(keys: %w(person full_name), case: :snake)
|
40
47
|
# reader.read(hash, 1) # returns 'John'
|
41
48
|
#
|
42
49
|
# @example
|
43
|
-
# reader = Arstotzka::Reader.new(%w(person age),
|
50
|
+
# reader = Arstotzka::Reader.new(keys: %w(person age), case: :upper_camel)
|
44
51
|
# reader.read(hash, 1) # returns 23
|
45
52
|
#
|
46
53
|
# @example
|
47
|
-
# reader = Arstotzka::Reader.new(%w(person car_collection model),
|
54
|
+
# reader = Arstotzka::Reader.new(keys: %w(person car_collection model), case: :snake)
|
48
55
|
# reader.read(hash, 1) # raises {Arstotzka::Exception::KeyNotFound}
|
49
56
|
#
|
50
57
|
# @example
|
51
|
-
# reader = Arstotzka::Reader.new(%w(person car_collection model),
|
58
|
+
# reader = Arstotzka::Reader.new(keys: %w(person car_collection model), case: :lower_camel)
|
52
59
|
# reader.read(hash, 1) # returns [
|
53
60
|
# # { maker: 'Ford', 'model' => 'Model A' },
|
54
61
|
# # { maker: 'BMW', 'model' => 'Jetta' }
|
55
62
|
# # ]
|
56
63
|
def read(hash, index)
|
57
|
-
key =
|
64
|
+
key = keys[index]
|
58
65
|
|
59
66
|
check_key!(hash, key)
|
60
67
|
|
@@ -63,20 +70,20 @@ module Arstotzka
|
|
63
70
|
|
64
71
|
# @private
|
65
72
|
#
|
66
|
-
# Checks if index is within
|
73
|
+
# Checks if index is within keys range
|
67
74
|
#
|
68
75
|
# @example
|
69
|
-
# reader = Arstotzka::Reader.new(%w(person full_name),
|
76
|
+
# reader = Arstotzka::Reader.new(%w(person full_name), case: :snake)
|
70
77
|
# reader.read(hash, 1) # returns false
|
71
78
|
# reader.read(hash, 2) # returns true
|
72
79
|
def ended?(index)
|
73
|
-
index >=
|
80
|
+
index >= keys.size
|
74
81
|
end
|
75
82
|
|
76
83
|
private
|
77
84
|
|
78
85
|
# @private
|
79
|
-
attr_reader :
|
86
|
+
attr_reader :keys, :options
|
80
87
|
|
81
88
|
# @private
|
82
89
|
#
|
@@ -115,14 +122,16 @@ module Arstotzka
|
|
115
122
|
#
|
116
123
|
# Transforms the key to have the correct case
|
117
124
|
#
|
118
|
-
# the possible
|
125
|
+
# the possible cases (instance attribute) are
|
119
126
|
# - lower_camel: for cammel case with first letter lowercase
|
120
127
|
# - upper_camel: for cammel case with first letter uppercase
|
121
128
|
# - snake: for snake case
|
122
129
|
#
|
123
130
|
# @param [String] key the key to be transformed
|
131
|
+
#
|
132
|
+
# @return [String] the string transformed
|
124
133
|
def change_case(key)
|
125
|
-
case
|
134
|
+
case options.case
|
126
135
|
when :lower_camel
|
127
136
|
key.camelize(:lower)
|
128
137
|
when :upper_camel
|
data/lib/arstotzka/type_cast.rb
CHANGED
@@ -84,7 +84,7 @@ module Arstotzka
|
|
84
84
|
# age: '10',
|
85
85
|
# }
|
86
86
|
#
|
87
|
-
#
|
87
|
+
# TypeCaster.new(age: '10').age
|
88
88
|
def to_integer(value)
|
89
89
|
value.to_i if value.present?
|
90
90
|
end
|
@@ -108,7 +108,7 @@ module Arstotzka
|
|
108
108
|
# payload: { 'key' => 'value' },
|
109
109
|
# }
|
110
110
|
#
|
111
|
-
# model.
|
111
|
+
# model.TypeCaster.new(hash)
|
112
112
|
#
|
113
113
|
# model.payload # returns '{"key"=>"value"}'
|
114
114
|
def to_string(value)
|
@@ -134,7 +134,7 @@ module Arstotzka
|
|
134
134
|
# price: '1.75'
|
135
135
|
# }
|
136
136
|
#
|
137
|
-
#
|
137
|
+
# TypeCaster.new(price: '1.75').price # returns 1.75
|
138
138
|
def to_float(value)
|
139
139
|
value.to_f if value.present?
|
140
140
|
end
|
data/lib/arstotzka/version.rb
CHANGED
data/lib/arstotzka/wrapper.rb
CHANGED
@@ -6,15 +6,22 @@ module Arstotzka
|
|
6
6
|
# Class responsible for wrapping / parsing a value fetched
|
7
7
|
class Wrapper
|
8
8
|
include Arstotzka::TypeCast
|
9
|
+
include Base
|
9
10
|
|
10
11
|
# Returns a new instance of Wrapper
|
11
12
|
#
|
12
|
-
# @
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
# @overload initialize(options_hash={})
|
14
|
+
# @param options_hash [Hash] options of initialization
|
15
|
+
# @option options_hash klass [Class] class to wrap the value
|
16
|
+
# @option options_hash type [String/Symbol] type to cast the value. The
|
17
|
+
# possible type_cast is defined by {TypeCast}
|
18
|
+
#
|
19
|
+
# @overload initialize(options)
|
20
|
+
# @param options [Arstotzka::Options] options of initialization object
|
21
|
+
#
|
22
|
+
# @return [Arstotzka::Wrapper]
|
23
|
+
def initialize(options = {})
|
24
|
+
self.options = options
|
18
25
|
end
|
19
26
|
|
20
27
|
# wrap a value
|
@@ -30,7 +37,7 @@ module Arstotzka
|
|
30
37
|
# end
|
31
38
|
# end
|
32
39
|
#
|
33
|
-
# wrapper = Arstotzka::Wrapper.new(
|
40
|
+
# wrapper = Arstotzka::Wrapper.new(klass: Person)
|
34
41
|
# wrapper.wrap('John') # retruns Person.new('John')
|
35
42
|
#
|
36
43
|
# @example Casting type
|
@@ -46,7 +53,7 @@ module Arstotzka
|
|
46
53
|
# end
|
47
54
|
# end
|
48
55
|
#
|
49
|
-
# wrapper = Arstotzka::Wrapper.new(type: :string,
|
56
|
+
# wrapper = Arstotzka::Wrapper.new(type: :string, klass: Request)
|
50
57
|
# request = wrapper.wrap(value)
|
51
58
|
#
|
52
59
|
# request.payload # returns '{"key"=>"value"}'
|
@@ -58,7 +65,8 @@ module Arstotzka
|
|
58
65
|
private
|
59
66
|
|
60
67
|
# @private
|
61
|
-
attr_reader :
|
68
|
+
attr_reader :options
|
69
|
+
delegate :klass, :type, to: :options
|
62
70
|
|
63
71
|
# @private
|
64
72
|
#
|
@@ -69,7 +77,7 @@ module Arstotzka
|
|
69
77
|
value = cast(value) if type? && !value.nil?
|
70
78
|
return if value.nil?
|
71
79
|
|
72
|
-
|
80
|
+
klass ? klass.new(value) : value
|
73
81
|
end
|
74
82
|
|
75
83
|
# @private
|
data/lib/arstotzka.rb
CHANGED
@@ -5,7 +5,7 @@ require 'active_support/all'
|
|
5
5
|
require 'sinclair'
|
6
6
|
|
7
7
|
# Concern that enables the translation of domain though the
|
8
|
-
# usage of the class method
|
8
|
+
# usage of the class method +expose+
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# json = <<-JSON
|
@@ -142,7 +142,7 @@ require 'sinclair'
|
|
142
142
|
#
|
143
143
|
# class Collector
|
144
144
|
# expose :finished_games, json: :hash,
|
145
|
-
# flatten: true,
|
145
|
+
# flatten: true, klass: Collector::Game,
|
146
146
|
# after: :filter_finished, compact: true,
|
147
147
|
# full_path: 'collections.games.titles'
|
148
148
|
#
|
@@ -164,6 +164,8 @@ require 'sinclair'
|
|
164
164
|
module Arstotzka
|
165
165
|
extend ActiveSupport::Concern
|
166
166
|
|
167
|
+
autoload :Base, 'arstotzka/base'
|
168
|
+
autoload :Options, 'arstotzka/options'
|
167
169
|
autoload :Builder, 'arstotzka/builder'
|
168
170
|
autoload :ClassMethods, 'arstotzka/class_methods'
|
169
171
|
autoload :Crawler, 'arstotzka/crawler'
|
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe Arstotzka::Builder do
|
6
6
|
describe 'yard' do
|
7
7
|
let!(:instance) { klass.new(hash) }
|
8
|
-
let(:
|
8
|
+
let(:options) { Arstotzka::Options.new(options_hash) }
|
9
9
|
let(:hash) do
|
10
10
|
{
|
11
11
|
'name' => { first: 'John', last: 'Williams' },
|
@@ -13,12 +13,12 @@ describe Arstotzka::Builder do
|
|
13
13
|
'cars' => 2.0
|
14
14
|
}
|
15
15
|
end
|
16
|
-
let(:builder) { described_class.new(attributes, klass,
|
16
|
+
let(:builder) { described_class.new(attributes, klass, options) }
|
17
17
|
|
18
18
|
describe '#first_name' do
|
19
|
-
let(:klass)
|
20
|
-
let(:attributes)
|
21
|
-
let(:
|
19
|
+
let(:klass) { Class.new(MyModel) }
|
20
|
+
let(:attributes) { [:first_name] }
|
21
|
+
let(:options_hash) { { full_path: 'name.first' } }
|
22
22
|
|
23
23
|
before do
|
24
24
|
builder.build
|
@@ -30,9 +30,9 @@ describe Arstotzka::Builder do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
describe '#age' do
|
33
|
-
let(:klass)
|
34
|
-
let(:attributes)
|
35
|
-
let(:
|
33
|
+
let(:klass) { Class.new(MyModel) }
|
34
|
+
let(:attributes) { [:age, 'cars'] }
|
35
|
+
let(:options_hash) { { type: :integer } }
|
36
36
|
|
37
37
|
before do
|
38
38
|
builder.build
|
@@ -48,9 +48,9 @@ describe Arstotzka::Builder do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
describe '#cars' do
|
51
|
-
let(:klass)
|
52
|
-
let(:attributes)
|
53
|
-
let(:
|
51
|
+
let(:klass) { Class.new(MyModel) }
|
52
|
+
let(:attributes) { [:age, 'cars'] }
|
53
|
+
let(:options_hash) { { type: :integer } }
|
54
54
|
|
55
55
|
before do
|
56
56
|
builder.build
|
@@ -5,11 +5,11 @@ require 'spec_helper'
|
|
5
5
|
describe Arstotzka::Crawler do
|
6
6
|
describe 'yard' do
|
7
7
|
subject(:crawler) do
|
8
|
-
described_class.new(
|
8
|
+
described_class.new(keys: keys, **options)
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:options) { {} }
|
12
|
-
let(:
|
12
|
+
let(:keys) { %w[person information first_name] }
|
13
13
|
let(:hash) do
|
14
14
|
{
|
15
15
|
person: {
|
@@ -25,15 +25,15 @@ describe Arstotzka::Crawler do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#value' do
|
28
|
-
context 'when hash contains the
|
28
|
+
context 'when hash contains the keys' do
|
29
29
|
it 'crawls to find the value' do
|
30
30
|
expect(crawler.value(hash)).to eq('John')
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
context 'when we have an array of arrays' do
|
35
|
-
let(:
|
36
|
-
let(:options) { { compact: true,
|
35
|
+
let(:keys) { %w[companies games hero_name] }
|
36
|
+
let(:options) { { compact: true, case: :snake } }
|
37
37
|
let(:hash) do
|
38
38
|
{
|
39
39
|
'companies' => [{
|
@@ -55,7 +55,7 @@ describe Arstotzka::Crawler do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
context 'with default value' do
|
58
|
-
let(:options) { { compact: true,
|
58
|
+
let(:options) { { compact: true, case: :snake, default: 'NO HERO' } }
|
59
59
|
|
60
60
|
it 'return default value for missed keys' do
|
61
61
|
expect(crawler.value(hash)).to eq([['NO HERO', 'Rakhar'], 'NO HERO'])
|
@@ -64,7 +64,7 @@ describe Arstotzka::Crawler do
|
|
64
64
|
|
65
65
|
context 'when block is given' do
|
66
66
|
subject(:crawler) do
|
67
|
-
described_class.new(
|
67
|
+
described_class.new(keys: keys, **options) { |value| value&.to_sym }
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'returns the post processed values' do
|
@@ -5,13 +5,13 @@ require 'spec_helper'
|
|
5
5
|
describe Arstotzka::Fetcher do
|
6
6
|
describe 'yard' do
|
7
7
|
describe '#fetch' do
|
8
|
-
subject(:fetcher) { described_class.new(hash, instance,
|
8
|
+
subject(:fetcher) { described_class.new(hash, instance, **options) }
|
9
9
|
|
10
10
|
let(:instance) { Account.new }
|
11
|
-
let(:path) { 'transactions' }
|
12
11
|
let(:options) do
|
13
12
|
{
|
14
|
-
|
13
|
+
path: 'transactions',
|
14
|
+
klass: Transaction,
|
15
15
|
after: :filter_income
|
16
16
|
}
|
17
17
|
end
|
@@ -4,9 +4,9 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Arstotzka::Reader do
|
6
6
|
describe 'yard' do
|
7
|
-
subject(:reader) { described_class.new(
|
7
|
+
subject(:reader) { described_class.new(keys: keys, case: case_type) }
|
8
8
|
|
9
|
-
let(:
|
9
|
+
let(:keys) { %w[person full_name] }
|
10
10
|
let(:case_type) { :snake }
|
11
11
|
|
12
12
|
describe '#read' do
|
@@ -27,7 +27,7 @@ describe Arstotzka::Reader do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'when key is missing' do
|
30
|
-
let(:
|
30
|
+
let(:keys) { %w[person car_collection model] }
|
31
31
|
|
32
32
|
it do
|
33
33
|
expect do
|
@@ -39,7 +39,7 @@ describe Arstotzka::Reader do
|
|
39
39
|
|
40
40
|
context 'when using lowerCamel' do
|
41
41
|
let(:case_type) { :lower_camel }
|
42
|
-
let(:
|
42
|
+
let(:keys) { %w[person car_collection model] }
|
43
43
|
|
44
44
|
it 'fetches the value using lower camel case key' do
|
45
45
|
expected = [
|
@@ -52,7 +52,7 @@ describe Arstotzka::Reader do
|
|
52
52
|
|
53
53
|
context 'when using UpperCamel' do
|
54
54
|
let(:case_type) { :upper_camel }
|
55
|
-
let(:
|
55
|
+
let(:keys) { %w[person age] }
|
56
56
|
|
57
57
|
it 'fetches the value using uper camel case key' do
|
58
58
|
expect(reader.read(hash, 1)).to eq(23)
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: truie
|
2
2
|
|
3
3
|
describe Arstotzka::Wrapper do
|
4
|
-
subject(:wrapper) { described_class.new(
|
4
|
+
subject(:wrapper) { described_class.new(klass: klass, type: type) }
|
5
5
|
|
6
6
|
let(:type) { nil }
|
7
|
-
let(:
|
7
|
+
let(:klass) { nil }
|
8
8
|
|
9
9
|
describe 'yard' do
|
10
10
|
describe '#wrap' do
|
11
|
-
context 'when
|
12
|
-
let(:
|
11
|
+
context 'when klass is defined' do
|
12
|
+
let(:klass) { Person }
|
13
13
|
let(:value) { 'john' }
|
14
14
|
|
15
|
-
it 'wraps value with the
|
15
|
+
it 'wraps value with the klass' do
|
16
16
|
expect(wrapper.wrap(value)).to eq(Person.new(value))
|
17
17
|
end
|
18
18
|
end
|
@@ -28,7 +28,7 @@ describe Arstotzka::Wrapper do
|
|
28
28
|
|
29
29
|
context 'when type and class is defined' do
|
30
30
|
let(:type) { :string }
|
31
|
-
let(:
|
31
|
+
let(:klass) { Request }
|
32
32
|
let(:value) { { 'key' => 'value' } }
|
33
33
|
let(:request) { wrapper.wrap(value) }
|
34
34
|
|
@@ -4,10 +4,10 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Arstotzka::Builder do
|
6
6
|
subject(:builder) do
|
7
|
-
described_class.new(attr_names,
|
7
|
+
described_class.new(attr_names, klass, **full_options)
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:
|
10
|
+
let(:klass) do
|
11
11
|
Class.new.tap do |c|
|
12
12
|
c.send(:attr_reader, :json)
|
13
13
|
c.send(:define_method, :initialize) do |json = {}|
|
@@ -21,15 +21,15 @@ describe Arstotzka::Builder do
|
|
21
21
|
let(:attr_name) { :name }
|
22
22
|
let(:attr_names) { [attr_name] }
|
23
23
|
let(:json) { {} }
|
24
|
-
let(:instance) {
|
25
|
-
let(:full_options) {
|
24
|
+
let(:instance) { klass.new(json) }
|
25
|
+
let(:full_options) { Arstotzka::Options::DEFAULT_OPTIONS.merge(options) }
|
26
26
|
|
27
27
|
describe '#build' do
|
28
28
|
context 'when it is called' do
|
29
29
|
it 'adds the reader' do
|
30
30
|
expect do
|
31
31
|
builder.build
|
32
|
-
end.to add_method(attr_name).to(
|
32
|
+
end.to add_method(attr_name).to(klass)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -78,7 +78,7 @@ describe Arstotzka::Builder do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
context 'when defining a fullpath' do
|
81
|
-
let(:options)
|
81
|
+
let(:options) { { full_path: 'user.name' } }
|
82
82
|
let(:attr_name) { :the_name }
|
83
83
|
|
84
84
|
it 'fetches the value within the json' do
|
@@ -89,7 +89,7 @@ describe Arstotzka::Builder do
|
|
89
89
|
|
90
90
|
context 'when wrapping with a class' do
|
91
91
|
let(:json) { { person: name } }
|
92
|
-
let(:options)
|
92
|
+
let(:options) { { klass: Person } }
|
93
93
|
let(:attr_name) { :person }
|
94
94
|
|
95
95
|
it do
|