arstotzka 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c670a2581e68a1b7e54d5451b6b425fde3cde0db
4
- data.tar.gz: 0f2d973a287534f68be841ebcbb63fc0e5f5babb
3
+ metadata.gz: a819ccb4eab671027d924859a3406ed34c119992
4
+ data.tar.gz: cb6617c7d4a846b7e7398d0eb68d3cbe9996f24c
5
5
  SHA512:
6
- metadata.gz: 1826c6c9b9017ce2f302ed930856acb4889eede6a203b25dc1674f1dfe545bae8407acbfaad4cee294782e2afaa11aca50ee39f95700756d6e62ab8cbf18bdc9
7
- data.tar.gz: 29f5570b7d161c62069512a9605fde0424c6ac9083ad7dc15d25b6a36e86afe747b6e3ad0abefd1a8d908c86b2b9df34415ea23543d8f2744286a017727ea012
6
+ metadata.gz: 999acf4da93d2c838bbf8d557f482db6b6bb001ad70ce55235eac8a486ca1f0c91609c0eb7c95f4afe92e3dc120b0e1d14ceffc6eee2b967b99aca10d59b1597
7
+ data.tar.gz: 5008b64f5c6bd7698ba26e61e8932562f4778a8fa3cd95547aa6a286e5af7cfa3b1177ca7907339b62c10fcdc2b1878818bd394c311f91a22744b5534cc14cdd
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2018-07-22 21:24:28 +0000 using RuboCop version 0.58.0.
3
+ # on 2018-07-25 18:12:13 +0000 using RuboCop version 0.58.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -11,10 +11,3 @@
11
11
  Metrics/ParameterLists:
12
12
  Exclude:
13
13
  - 'lib/arstotzka/builder.rb'
14
-
15
- # Offense count: 1
16
- Style/Documentation:
17
- Exclude:
18
- - 'spec/**/*'
19
- - 'test/**/*'
20
- - 'lib/arstotzka.rb'
data/README.md CHANGED
@@ -12,7 +12,9 @@ that tries to crawl through a hash and has to constantly check for nil values or
12
12
  also, this concern, like openstruct, allow the json to be manipulated as an object, but
13
13
  avoids method missing by aways having the declarated methods, even if that means nil return
14
14
 
15
- Json Parser is also usefull when you need keys case changed or data type cast
15
+ Arstotzka is also usefull when you need keys case changed or data type cast as it was developed
16
+ to be a bridge between a rails application and a Java API (Java APIs use cameCase for
17
+ JSON keys)
16
18
 
17
19
  Instalation
18
20
  ---------------
@@ -4,6 +4,163 @@ require 'active_support'
4
4
  require 'active_support/all'
5
5
  require 'sinclair'
6
6
 
7
+ # Concern that enables the translation of domain though the
8
+ # usage of the class method `expose`
9
+ #
10
+ # @example
11
+ # json = <<-JSON
12
+ # {
13
+ # "person": {
14
+ # "fullName": "Kelly Khan",
15
+ # "age": 32,
16
+ # "gender": "woman"
17
+ # },
18
+ # "collections": {
19
+ # "cars": [{
20
+ # "maker": "Volkswagen",
21
+ # "model": "Jetta",
22
+ # "units": [{
23
+ # "nickName": "Betty",
24
+ # "year": 2013
25
+ # }, {
26
+ # "nickName": "Roger",
27
+ # "year": 2014
28
+ # }]
29
+ # }, {
30
+ # "maker": "Ferrari",
31
+ # "model": "Ferrari X1",
32
+ # "units": [{
33
+ # "nickName": "Geronimo",
34
+ # "year": 2014
35
+ # }]
36
+ # }, {
37
+ # "maker": "Fiat",
38
+ # "model": "Uno",
39
+ # "units": [{
40
+ # "year": 1998
41
+ # }]
42
+ # }],
43
+ # "games":[{
44
+ # "producer": "Lucas Pope",
45
+ # "titles": [{
46
+ # "name": "papers, please",
47
+ # "played": "10.2%"
48
+ # }, {
49
+ # "name": "TheNextBigThing",
50
+ # "played": "100%"
51
+ # }]
52
+ # }, {
53
+ # "producer": "Nintendo",
54
+ # "titles": [{
55
+ # "name": "Zelda",
56
+ # "played": "90%"
57
+ # }]
58
+ # }, {
59
+ # "producer": "BadCompany"
60
+ # }]
61
+ # }
62
+ # }
63
+ # JSON
64
+ #
65
+ # hash = JSON.parse(json)
66
+ #
67
+ # @example
68
+ # class Collector
69
+ # include Arstotzka
70
+ #
71
+ # MALE = 'male'
72
+ # FEMALE= 'female'
73
+ #
74
+ # attr_reader :hash
75
+ #
76
+ # expose :full_name, :age, path: :person, json: :hash
77
+ # expose :gender, path: :person, type: :gender, cached: true, json: :hash
78
+ #
79
+ # def initialize(hash = {})
80
+ # @hash = hash
81
+ # end
82
+ # end
83
+ #
84
+ # module Arstotzka
85
+ # module TypeCast
86
+ # def to_gender(value)
87
+ # case value
88
+ # when 'man'
89
+ # Collector::MALE
90
+ # when 'woman'
91
+ # Collector::FEMALE
92
+ # else
93
+ # raise 'invalid gender'
94
+ # end
95
+ # end
96
+ # end
97
+ # end
98
+ #
99
+ # collector = Collector.new(hash)
100
+ # collector.full_name # returns 'Kelly Khan'
101
+ # collector.age # returns 32
102
+ # collector.gender # returns Collector::FEMALE
103
+ #
104
+ # hash['person']['fullName'] = 'Robert'
105
+ # collector.full_name # returns 'Robert'
106
+ #
107
+ # hash['person']['gender'] = 'man'
108
+ # collector.gender # returns Collector::FEMALE as it was cached
109
+ #
110
+ # @example
111
+ # class Collector
112
+ # expose :car_names, flatten: true, compact: false, json: :hash,
113
+ # default: 'MissingName',
114
+ # full_path: 'collections.cars.units.nick_name'
115
+ # end
116
+ #
117
+ # collector = Collector.new(hash)
118
+ # collector.car_names # returns [
119
+ # # 'Betty', 'Roger',
120
+ # # 'Geronimo', 'MissingName'
121
+ # # ]
122
+ #
123
+ # @example
124
+ # class Collector
125
+ # class Game
126
+ # include Arstotzka
127
+ #
128
+ # attr_reader :json
129
+ #
130
+ # expose :name
131
+ # expose :played, type: :float
132
+ #
133
+ # def initialize(json)
134
+ # @json = json
135
+ # end
136
+ #
137
+ # def finished?
138
+ # played > 85.0
139
+ # end
140
+ # end
141
+ # end
142
+ #
143
+ # class Collector
144
+ # expose :finished_games, json: :hash,
145
+ # flatten: true, class: Collector::Game,
146
+ # after: :filter_finished, compact: true,
147
+ # full_path: 'collections.games.titles'
148
+ #
149
+ # private
150
+ #
151
+ # def filter_finished(games)
152
+ # games.select(&:finished?)
153
+ # end
154
+ # end
155
+ #
156
+ # collector = Collector.new(hash)
157
+ # collector.finished_games # returns [
158
+ # # Collector::Game.new(name: "TheNextBigThing", played: 100.0),
159
+ # # Collector::Game.new(name: "Zelda", played: 90.0)
160
+ # # ]
161
+ #
162
+ # @see Arstotzka::Builder
163
+ # @see Arstotzka::ClassMethods
7
164
  module Arstotzka
8
165
  extend ActiveSupport::Concern
9
166
 
@@ -19,12 +19,14 @@ module Arstotzka
19
19
  # 'cars' => 2.0
20
20
  # )
21
21
  #
22
- # builder = Arstotzka::Builder.new([ :first_name ], MyModel, full_path: 'name.first')
22
+ # options = Arstotzka::Builder::DEFAULT_OPTIONS.merge(full_path: 'name.first')
23
+ # builder = Arstotzka::Builder.new([ :first_name ], MyModel, options)
23
24
  # builder.build
24
25
  #
25
26
  # instance.first_name # returns 'John'
26
27
  #
27
- # builder = Arstotzka::Builder.new([ :age, :cars ], MyModel, type: :integer)
28
+ # options = Arstotzka::Builder::DEFAULT_OPTIONS.merge(type: :integer)
29
+ # builder = Arstotzka::Builder.new([ :age, :cars ], MyModel, options)
28
30
  # builder.build
29
31
  #
30
32
  # instance.age # returns 20
@@ -33,13 +35,16 @@ module Arstotzka
33
35
  # @see https://www.rubydoc.info/gems/sinclair Sinclair
34
36
  class Builder < Sinclair
35
37
  DEFAULT_OPTIONS = {
38
+ json: :json,
39
+ path: nil,
40
+ full_path: nil,
41
+ cached: false,
36
42
  after: false,
37
43
  case: :lower_camel,
38
44
  class: nil,
39
- compact: false,
40
- default: nil,
45
+ compact: false,
46
+ default: nil,
41
47
  flatten: false,
42
- json: :json,
43
48
  type: :none
44
49
  }.freeze
45
50
 
@@ -71,10 +76,8 @@ module Arstotzka
71
76
  # - integer
72
77
  # - string
73
78
  # - float
74
- def initialize(attr_names, clazz,
75
- json: :json, path: nil, full_path: nil, cached: false,
76
- **options)
77
- super(clazz, DEFAULT_OPTIONS.merge(options.symbolize_keys))
79
+ def initialize(attr_names, clazz, json:, path:, full_path:, cached:, **options)
80
+ super(clazz, options)
78
81
 
79
82
  @attr_names = attr_names
80
83
  @path = path
@@ -35,6 +35,7 @@ module Arstotzka
35
35
  # https://www.rubydoc.info/gems/activesupport/5.0.0.1/ActiveSupport/Concern
36
36
  # ActiveSupport::Concern
37
37
  def expose(*attr_names, **options)
38
+ options = Builder::DEFAULT_OPTIONS.merge(options.symbolize_keys)
38
39
  Builder.new(attr_names, self, options).build
39
40
  end
40
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Arstotzka
4
- VERSION = '1.0.2'
4
+ VERSION = '1.0.3'
5
5
  end
@@ -5,6 +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(:full_options) { described_class::DEFAULT_OPTIONS.merge(options) }
8
9
  let(:hash) do
9
10
  {
10
11
  'name' => { first: 'John', last: 'Williams' },
@@ -12,10 +13,12 @@ describe Arstotzka::Builder do
12
13
  'cars' => 2.0
13
14
  }
14
15
  end
16
+ let(:builder) { described_class.new(attributes, klass, full_options) }
15
17
 
16
18
  describe '#first_name' do
17
- let(:klass) { Class.new(MyModel) }
18
- let(:builder) { described_class.new([:first_name], klass, full_path: 'name.first') }
19
+ let(:klass) { Class.new(MyModel) }
20
+ let(:attributes) { [:first_name] }
21
+ let(:options) { { full_path: 'name.first' } }
19
22
 
20
23
  before do
21
24
  builder.build
@@ -27,8 +30,9 @@ describe Arstotzka::Builder do
27
30
  end
28
31
 
29
32
  describe '#age' do
30
- let(:klass) { Class.new(MyModel) }
31
- let(:builder) { described_class.new([:age, 'cars'], klass, type: :integer) }
33
+ let(:klass) { Class.new(MyModel) }
34
+ let(:attributes) { [:age, 'cars'] }
35
+ let(:options) { { type: :integer } }
32
36
 
33
37
  before do
34
38
  builder.build
@@ -44,8 +48,9 @@ describe Arstotzka::Builder do
44
48
  end
45
49
 
46
50
  describe '#cars' do
47
- let(:klass) { Class.new(MyModel) }
48
- let(:builder) { described_class.new([:age, 'cars'], klass, type: :integer) }
51
+ let(:klass) { Class.new(MyModel) }
52
+ let(:attributes) { [:age, 'cars'] }
53
+ let(:options) { { type: :integer } }
49
54
 
50
55
  before do
51
56
  builder.build
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Arstotzka do
6
+ describe :yard do
7
+ subject { Collector.new(hash) }
8
+
9
+ let(:hash) { JSON.parse json }
10
+ let(:json) do
11
+ <<-JSON
12
+ {
13
+ "person": {
14
+ "fullName": "Kelly Khan",
15
+ "age": 32,
16
+ "gender": "woman"
17
+ },
18
+ "collections": {
19
+ "cars": [{
20
+ "maker": "Volkswagen",
21
+ "model": "Jetta",
22
+ "units": [{
23
+ "nickName": "Betty",
24
+ "year": 2013
25
+ }, {
26
+ "nickName": "Roger",
27
+ "year": 2014
28
+ }]
29
+ }, {
30
+ "maker": "Ferrari",
31
+ "model": "Ferrari X1",
32
+ "units": [{
33
+ "nickName": "Geronimo",
34
+ "year": 2014
35
+ }]
36
+ }, {
37
+ "maker": "Fiat",
38
+ "model": "Uno",
39
+ "units": [{
40
+ "year": 1998
41
+ }]
42
+ }],
43
+ "games":[{
44
+ "producer": "Lucas Pope",
45
+ "titles": [{
46
+ "name": "papers, please",
47
+ "played": "10.2%"
48
+ }, {
49
+ "name": "TheNextBigThing",
50
+ "played": "100%"
51
+ }]
52
+ }, {
53
+ "producer": "Nintendo",
54
+ "titles": [{
55
+ "name": "Zelda",
56
+ "played": "90%"
57
+ }]
58
+ }, {
59
+ "producer": "BadCompany"
60
+ }]
61
+ }
62
+ }
63
+ JSON
64
+ end
65
+
66
+ describe '#full_name' do
67
+ it 'returns the full_name' do
68
+ expect(subject.full_name).to eq('Kelly Khan')
69
+ end
70
+
71
+ it 'does not cache name' do
72
+ expect do
73
+ hash['person']['fullName'] = 'Robert'
74
+ end.to change(subject, :full_name).to('Robert')
75
+ end
76
+ end
77
+
78
+ describe '#age' do
79
+ it 'returns the age' do
80
+ expect(subject.age).to eq(32)
81
+ end
82
+ end
83
+
84
+ describe '#gender' do
85
+ it 'returns person gender' do
86
+ expect(subject.gender).to eq(Collector::FEMALE)
87
+ end
88
+
89
+ it 'does caches gender' do
90
+ expect do
91
+ hash['person']['gender'] = 'man'
92
+ end.not_to change(subject, :gender)
93
+ end
94
+ end
95
+
96
+ describe '#car_names' do
97
+ it 'returns the nick names of the cars' do
98
+ expect(subject.car_names).to eq(%w[Betty Roger Geronimo MissingName])
99
+ end
100
+ end
101
+
102
+ describe '#finished_games' do
103
+ it 'returns the finished games' do
104
+ expected = [
105
+ Collector::Game.new(name: 'TheNextBigThing', played: 100.0),
106
+ Collector::Game.new(name: 'Zelda', played: 90.0)
107
+ ]
108
+ expect(subject.finished_games).to eq(expected)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -12,15 +12,16 @@ describe Arstotzka::Builder do
12
12
  end
13
13
  end
14
14
 
15
- let(:options) { {} }
16
- let(:name) { 'Robert' }
17
- let(:attr_name) { :name }
18
- let(:attr_names) { [attr_name] }
19
- let(:json) { {} }
20
- let(:instance) { clazz.new(json) }
15
+ let(:options) { {} }
16
+ let(:name) { 'Robert' }
17
+ let(:attr_name) { :name }
18
+ let(:attr_names) { [attr_name] }
19
+ let(:json) { {} }
20
+ let(:instance) { clazz.new(json) }
21
+ let(:full_options) { described_class::DEFAULT_OPTIONS.merge(options) }
21
22
 
22
23
  subject do
23
- described_class.new(attr_names, clazz, **options)
24
+ described_class.new(attr_names, clazz, **full_options)
24
25
  end
25
26
 
26
27
  describe '#build' do
@@ -13,7 +13,6 @@ support_files = File.expand_path('spec/support/**/*.rb')
13
13
  Dir[support_files].sort.each { |file| require file }
14
14
 
15
15
  RSpec.configure do |config|
16
- config.treat_symbols_as_metadata_keys_with_true_values = true
17
16
  config.run_all_when_everything_filtered = true
18
17
  config.filter_run :focus
19
18
  config.filter_run_excluding :integration unless ENV['ALL']
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Collector
4
+ include Arstotzka
5
+
6
+ MALE = 'male'
7
+ FEMALE = 'female'
8
+
9
+ attr_reader :hash
10
+
11
+ expose :full_name, :age, path: :person, json: :hash
12
+ expose :gender, path: :person, type: :gender, cached: true, json: :hash
13
+ expose :car_names, flatten: true, compact: false, json: :hash,
14
+ default: 'MissingName',
15
+ full_path: 'collections.cars.units.nick_name'
16
+ expose :finished_games, json: :hash,
17
+ flatten: true, class: Collector::Game,
18
+ after: :filter_finished, compact: true,
19
+ full_path: 'collections.games.titles'
20
+
21
+ def initialize(hash = {})
22
+ @hash = hash
23
+ end
24
+
25
+ private
26
+
27
+ def filter_finished(games)
28
+ games.select(&:finished?)
29
+ end
30
+ end
31
+
32
+ module Arstotzka
33
+ module TypeCast
34
+ def to_gender(value)
35
+ case value
36
+ when 'man'
37
+ Collector::MALE
38
+ when 'woman'
39
+ Collector::FEMALE
40
+ else
41
+ raise 'invalid gender'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Collector
4
+ class Game
5
+ include Arstotzka
6
+
7
+ attr_reader :json
8
+
9
+ expose :name
10
+ expose :played, type: :float
11
+
12
+ def initialize(json)
13
+ @json = json
14
+ end
15
+
16
+ def ==(other)
17
+ return false if other.class != self.class
18
+ name == other.name && played == other.played
19
+ end
20
+
21
+ def finished?
22
+ played > 85.0
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arstotzka
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darthjee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-22 00:00:00.000000000 Z
11
+ date: 2018-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -193,6 +193,7 @@ files:
193
193
  - spec/integration/yard/arstotzka/fetcher_spec.rb
194
194
  - spec/integration/yard/arstotzka/reader_spec.rb
195
195
  - spec/integration/yard/arstotzka/wrapper_spec.rb
196
+ - spec/integration/yard/arstotzka_spec.rb
196
197
  - spec/lib/arstotzka/builder_spec.rb
197
198
  - spec/lib/arstotzka/crawler_spec.rb
198
199
  - spec/lib/arstotzka/fetcher_spec.rb
@@ -207,6 +208,8 @@ files:
207
208
  - spec/support/models/arstotzka/fetcher/dummy.rb
208
209
  - spec/support/models/arstotzka/type_cast.rb
209
210
  - spec/support/models/arstotzka/wrapper/dummy.rb
211
+ - spec/support/models/collector.rb
212
+ - spec/support/models/collector/game.rb
210
213
  - spec/support/models/game.rb
211
214
  - spec/support/models/house.rb
212
215
  - spec/support/models/my_model.rb
@@ -253,6 +256,7 @@ test_files:
253
256
  - spec/integration/yard/arstotzka/fetcher_spec.rb
254
257
  - spec/integration/yard/arstotzka/reader_spec.rb
255
258
  - spec/integration/yard/arstotzka/wrapper_spec.rb
259
+ - spec/integration/yard/arstotzka_spec.rb
256
260
  - spec/lib/arstotzka/builder_spec.rb
257
261
  - spec/lib/arstotzka/crawler_spec.rb
258
262
  - spec/lib/arstotzka/fetcher_spec.rb
@@ -267,6 +271,8 @@ test_files:
267
271
  - spec/support/models/arstotzka/fetcher/dummy.rb
268
272
  - spec/support/models/arstotzka/type_cast.rb
269
273
  - spec/support/models/arstotzka/wrapper/dummy.rb
274
+ - spec/support/models/collector.rb
275
+ - spec/support/models/collector/game.rb
270
276
  - spec/support/models/game.rb
271
277
  - spec/support/models/house.rb
272
278
  - spec/support/models/my_model.rb