api_struct 1.0.1 → 1.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b4ddea2489ecf3ef083cd6b4ba06a1e5b1d2fdf
4
- data.tar.gz: 5d55b25bec067bccf2fe8785badf9770937fc077
3
+ metadata.gz: 1846d9253d9d3bb8e7d8ed18ba445cebabf26b27
4
+ data.tar.gz: cdd2bc6c8104216e2938c2369120daeaaa1c0f0f
5
5
  SHA512:
6
- metadata.gz: e596aef0eb1223dc8477f18822153b92505599d4cd8cc5657d32cdade2a80c0a10febfb1b73e0a33d37b103b653084723c0f633356d032b8a361bb613ee1fe58
7
- data.tar.gz: 1ac9539e5216151b7cffae6b6973a369a0f095adea730613e9284059c91a2b129f55a42ff4cbad416d43927b51aebb2e9da890ead281be1893f51bd993787fc2
6
+ metadata.gz: 10c829780bff7016d56f7b3f53cd4b8b87e2a17193699c99653d5d7c5cedfb820603686992287198de61bebf05dd2a98e314046b4020a3b71c7301dcd8debb6e
7
+ data.tar.gz: de365513a4d9f53c31077379b95ae81f7cc47d464bb1043d844ee4cb2eec32670f9b43423130919c39cb481656b275db4fd74f4bf2cbae02ae0ee29a2c17691d
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- api_struct (1.0.0)
4
+ api_struct (1.0.1)
5
5
  dry-configurable (~> 0.7.0)
6
+ dry-inflector (~> 0.1.2)
6
7
  dry-monads (~> 1.0)
7
8
  hashie (~> 3.5, >= 3.5.6)
8
9
  http (>= 2.0.3)
@@ -15,7 +16,7 @@ GEM
15
16
  ast (2.3.0)
16
17
  byebug (9.1.0)
17
18
  coderay (1.1.2)
18
- concurrent-ruby (1.1.3)
19
+ concurrent-ruby (1.1.5)
19
20
  crack (0.4.3)
20
21
  safe_yaml (~> 1.0.0)
21
22
  diff-lcs (1.3)
@@ -23,17 +24,18 @@ GEM
23
24
  unf (>= 0.0.5, < 1.0.0)
24
25
  dry-configurable (0.7.0)
25
26
  concurrent-ruby (~> 1.0)
26
- dry-core (0.4.7)
27
+ dry-core (0.4.8)
27
28
  concurrent-ruby (~> 1.0)
28
- dry-equalizer (0.2.1)
29
- dry-monads (1.1.0)
29
+ dry-equalizer (0.2.2)
30
+ dry-inflector (0.1.2)
31
+ dry-monads (1.2.0)
30
32
  concurrent-ruby (~> 1.0)
31
33
  dry-core (~> 0.4, >= 0.4.4)
32
34
  dry-equalizer
33
35
  ffaker (2.8.0)
34
36
  hashdiff (0.3.7)
35
37
  hashie (3.6.0)
36
- http (4.0.0)
38
+ http (4.1.1)
37
39
  addressable (~> 2.3)
38
40
  http-cookie (~> 1.0)
39
41
  http-form_data (~> 2.0)
@@ -80,7 +82,7 @@ GEM
80
82
  safe_yaml (1.0.4)
81
83
  unf (0.1.4)
82
84
  unf_ext
83
- unf_ext (0.0.7.5)
85
+ unf_ext (0.0.7.6)
84
86
  unicode-display_width (1.3.0)
85
87
  vcr (3.0.3)
86
88
  webmock (3.2.1)
@@ -103,4 +105,4 @@ DEPENDENCIES
103
105
  webmock (~> 3.2, >= 3.2.1)
104
106
 
105
107
  BUNDLED WITH
106
- 1.17.1
108
+ 1.17.3
data/README.md CHANGED
@@ -38,7 +38,7 @@ ApiStruct::Settings.configure do |config|
38
38
  },
39
39
  second_api: {
40
40
  root: 'http://localhost:3001/api/v1',
41
- # etc...
41
+ params: { token: 'Default token' }
42
42
  }
43
43
  }
44
44
  end
data/api_struct.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency 'dry-monads', '~> 1.0'
22
22
  spec.add_dependency 'dry-configurable', '~> 0.7.0'
23
+ spec.add_dependency 'dry-inflector', '~> 0.1.2'
23
24
  spec.add_dependency 'http', '>= 2.0.3'
24
25
  spec.add_dependency 'hashie', '~> 3.5', '>= 3.5.6'
25
26
 
data/lib/api_struct.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'http'
2
2
  require 'dry/monads/result'
3
3
  require 'dry-configurable'
4
+ require 'dry/inflector'
4
5
  require 'json'
5
6
  require 'hashie'
6
7
 
@@ -13,6 +13,7 @@ module ApiStruct
13
13
  return super unless endpoints.keys.include?(method_name)
14
14
 
15
15
  define_method(:api_root) { endpoints[method_name][:root] }
16
+ define_method(:default_params) { endpoints[method_name][:params] || {} }
16
17
  define_method(:default_path) { first_arg(args) }
17
18
 
18
19
  define_method(:headers) do
@@ -25,6 +26,7 @@ module ApiStruct
25
26
  HTTP_METHODS.each do |http_method|
26
27
  define_method http_method do |*args, **options|
27
28
  begin
29
+ options[:params] = default_params.merge(options[:params] || {})
28
30
  wrap client.send(http_method, build_url(args, options), options)
29
31
  rescue HTTP::ConnectionError => e
30
32
  failure(body: e.message, status: :not_connected)
@@ -1,11 +1,7 @@
1
1
  module Concerns
2
2
  module Underscore
3
3
  def underscore(camel_cased_word)
4
- camel_cased_word.gsub(/::/, '/')
5
- .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
6
- .gsub(/([a-z\d])([A-Z])/,'\1_\2')
7
- .tr("-", "_")
8
- .downcase
4
+ Dry::Inflector.new.underscore(camel_cased_word)
9
5
  end
10
6
  end
11
7
  end
@@ -76,7 +76,12 @@ module ApiStruct
76
76
  private
77
77
 
78
78
  def extract_attributes(attributes)
79
- attributes.select { |key, _value| self.class.entity_attributes.include?(key.to_sym) }
79
+ formatted_attributes = attributes.map { |name, value| [format_name(name), value] }.to_h
80
+ formatted_attributes.select { |key, _value| self.class.entity_attributes.include?(key.to_sym) }
81
+ end
82
+
83
+ def format_name(name)
84
+ Dry::Inflector.new.underscore(name).to_sym
80
85
  end
81
86
  end
82
87
 
@@ -1,3 +1,3 @@
1
1
  module ApiStruct
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
@@ -1,7 +1,10 @@
1
1
  describe ApiStruct::Client do
2
2
  extend Support::Stub
3
- let(:api_root) { 'https://jsonplaceholder.typicode.com' }
4
- stub_api('https://jsonplaceholder.typicode.com')
3
+ API_ROOT = 'https://jsonplaceholder.typicode.com'
4
+
5
+ let(:api_root) { API_ROOT }
6
+ stub_api(API_ROOT)
7
+ let(:client) { StubClient.new }
5
8
 
6
9
  class StubClient < ApiStruct::Client
7
10
  stub_api :posts
@@ -17,7 +20,6 @@ describe ApiStruct::Client do
17
20
 
18
21
  context 'build url options' do
19
22
  context 'url options' do
20
- let(:client) { StubClient.new }
21
23
  it ' should replace /posts/users/:id to /posts/users if URL option didnt provided' do
22
24
  url = client.send(:build_url, 'users/:id', {})
23
25
  expect(url).to eq api_root + '/posts/users'
@@ -57,9 +59,10 @@ describe ApiStruct::Client do
57
59
  expect(url).to eq api_root + '/users/1/posts/2'
58
60
  end
59
61
  end
62
+
60
63
  it 'should build url with prefix' do
61
64
  VCR.use_cassette('users/1/posts') do
62
- response = StubClient.new.get(prefix: 'users/:id', id: 1)
65
+ response = client.get(prefix: 'users/:id', id: 1)
63
66
  expect(response).to be_success
64
67
  expect(response.value!).to be_kind_of Array
65
68
  expect(response.value!).not_to be_empty
@@ -68,7 +71,7 @@ describe ApiStruct::Client do
68
71
 
69
72
  it 'should build url with custom path' do
70
73
  VCR.use_cassette('todos') do
71
- response = StubClient.new.get(path: 'todos/1')
74
+ response = client.get(path: 'todos/1')
72
75
  expect(response).to be_success
73
76
  expect(response.value![:id]).to eq(1)
74
77
  expect(response.value![:title]).not_to be_empty
@@ -76,9 +79,28 @@ describe ApiStruct::Client do
76
79
  end
77
80
  end
78
81
 
82
+ context 'Default params' do
83
+ let(:user_id) { 2 }
84
+
85
+ before do
86
+ allow(client).to receive(:default_params).and_return(userId: user_id)
87
+ end
88
+
89
+ it 'should build url with default params' do
90
+ VCR.use_cassette('user_todos') do
91
+ response = client.get(path: 'todos')
92
+
93
+ expect(response).to be_success
94
+ response.value!.each do |response|
95
+ expect(response[:userId]).to eq(user_id)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
79
101
  it 'should build url with prefix as array' do
80
102
  VCR.use_cassette('todos') do
81
- response = StubClient.new.get(path: [:todos, 1])
103
+ response = client.get(path: [:todos, 1])
82
104
  expect(response).to be_success
83
105
  expect(response.value![:id]).to eq(1)
84
106
  expect(response.value![:title]).not_to be_empty
@@ -90,7 +112,7 @@ describe ApiStruct::Client do
90
112
  context 'GET' do
91
113
  it 'when successful response' do
92
114
  VCR.use_cassette('posts/show_success') do
93
- response = StubClient.new.show(1)
115
+ response = client.show(1)
94
116
  expect(response).to be_success
95
117
  expect(response.value![:id]).to eq(1)
96
118
  expect(response.value![:title]).not_to be_empty
@@ -99,7 +121,7 @@ describe ApiStruct::Client do
99
121
 
100
122
  it 'when failed response' do
101
123
  VCR.use_cassette('posts/show_failure') do
102
- response = StubClient.new.show(101)
124
+ response = client.show(101)
103
125
  expect(response).to be_failure
104
126
  expect(response.failure.status).to eq(404)
105
127
  end
@@ -107,7 +129,7 @@ describe ApiStruct::Client do
107
129
 
108
130
  it 'when failed response with html response' do
109
131
  VCR.use_cassette('posts/show_failure_html') do
110
- response = StubClient.new.show(101)
132
+ response = client.show(101)
111
133
  body = response.failure.body
112
134
  expect(response).to be_failure
113
135
  expect(response.failure.status).to eq(404)
@@ -120,7 +142,7 @@ describe ApiStruct::Client do
120
142
  context 'PATCH' do
121
143
  it 'when successful response' do
122
144
  VCR.use_cassette('posts/update_success') do
123
- response = StubClient.new.update(1, title: FFaker::Name.name)
145
+ response = client.update(1, title: FFaker::Name.name)
124
146
  expect(response).to be_success
125
147
  expect(response.value![:id]).to eq(1)
126
148
  end
@@ -26,7 +26,7 @@ describe ApiStruct::Entity do
26
26
  client_service StubClient, prefix: :only, only: :index
27
27
  client_service StubClient, prefix: :except, except: :show
28
28
 
29
- attr_entity :id, :title
29
+ attr_entity :id, :title, :camel_case
30
30
 
31
31
  has_entity :nested_entity, as: StubNestedEntity
32
32
  has_entities :another_nested_entities, as: StubNestedEntity
@@ -119,6 +119,7 @@ describe ApiStruct::Entity do
119
119
  expect(entity).to be_success
120
120
  expect(entity.id).to eq(1)
121
121
  expect(entity.title).not_to be_empty
122
+ expect(entity.camel_case).not_to be_empty
122
123
  end
123
124
  end
124
125
 
@@ -66,6 +66,7 @@ http_interactions:
66
66
  "userId": 1,
67
67
  "id": 1,
68
68
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
69
+ "camelCase": "camel case property",
69
70
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
70
71
  }
71
72
  http_version:
@@ -0,0 +1,189 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://jsonplaceholder.typicode.com/todos?userId=2
6
+ body:
7
+ encoding: UTF-8
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Content-Type:
13
+ - application/json
14
+ Connection:
15
+ - close
16
+ Host:
17
+ - jsonplaceholder.typicode.com
18
+ User-Agent:
19
+ - http.rb/4.1.1
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Wed, 17 Apr 2019 18:24:07 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - close
33
+ Set-Cookie:
34
+ - __cfduid=dc82c08fc0528b00d44fd9dc69a3d5bf91555525447; expires=Thu, 16-Apr-20
35
+ 18:24:07 GMT; path=/; domain=.typicode.com; HttpOnly
36
+ X-Powered-By:
37
+ - Express
38
+ Vary:
39
+ - Origin, Accept-Encoding
40
+ Access-Control-Allow-Credentials:
41
+ - 'true'
42
+ Cache-Control:
43
+ - public, max-age=14400
44
+ Pragma:
45
+ - no-cache
46
+ Expires:
47
+ - Wed, 17 Apr 2019 22:24:07 GMT
48
+ X-Content-Type-Options:
49
+ - nosniff
50
+ Etag:
51
+ - W/"940-PY6FbG4RbU9NVn6pD/xl3LdEHgs"
52
+ Via:
53
+ - 1.1 vegur
54
+ Cf-Cache-Status:
55
+ - HIT
56
+ Expect-Ct:
57
+ - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
58
+ Server:
59
+ - cloudflare
60
+ Cf-Ray:
61
+ - 4c906f20ea39cc81-WAW
62
+ body:
63
+ encoding: UTF-8
64
+ string: |-
65
+ [
66
+ {
67
+ "userId": 2,
68
+ "id": 21,
69
+ "title": "suscipit repellat esse quibusdam voluptatem incidunt",
70
+ "completed": false
71
+ },
72
+ {
73
+ "userId": 2,
74
+ "id": 22,
75
+ "title": "distinctio vitae autem nihil ut molestias quo",
76
+ "completed": true
77
+ },
78
+ {
79
+ "userId": 2,
80
+ "id": 23,
81
+ "title": "et itaque necessitatibus maxime molestiae qui quas velit",
82
+ "completed": false
83
+ },
84
+ {
85
+ "userId": 2,
86
+ "id": 24,
87
+ "title": "adipisci non ad dicta qui amet quaerat doloribus ea",
88
+ "completed": false
89
+ },
90
+ {
91
+ "userId": 2,
92
+ "id": 25,
93
+ "title": "voluptas quo tenetur perspiciatis explicabo natus",
94
+ "completed": true
95
+ },
96
+ {
97
+ "userId": 2,
98
+ "id": 26,
99
+ "title": "aliquam aut quasi",
100
+ "completed": true
101
+ },
102
+ {
103
+ "userId": 2,
104
+ "id": 27,
105
+ "title": "veritatis pariatur delectus",
106
+ "completed": true
107
+ },
108
+ {
109
+ "userId": 2,
110
+ "id": 28,
111
+ "title": "nesciunt totam sit blanditiis sit",
112
+ "completed": false
113
+ },
114
+ {
115
+ "userId": 2,
116
+ "id": 29,
117
+ "title": "laborum aut in quam",
118
+ "completed": false
119
+ },
120
+ {
121
+ "userId": 2,
122
+ "id": 30,
123
+ "title": "nemo perspiciatis repellat ut dolor libero commodi blanditiis omnis",
124
+ "completed": true
125
+ },
126
+ {
127
+ "userId": 2,
128
+ "id": 31,
129
+ "title": "repudiandae totam in est sint facere fuga",
130
+ "completed": false
131
+ },
132
+ {
133
+ "userId": 2,
134
+ "id": 32,
135
+ "title": "earum doloribus ea doloremque quis",
136
+ "completed": false
137
+ },
138
+ {
139
+ "userId": 2,
140
+ "id": 33,
141
+ "title": "sint sit aut vero",
142
+ "completed": false
143
+ },
144
+ {
145
+ "userId": 2,
146
+ "id": 34,
147
+ "title": "porro aut necessitatibus eaque distinctio",
148
+ "completed": false
149
+ },
150
+ {
151
+ "userId": 2,
152
+ "id": 35,
153
+ "title": "repellendus veritatis molestias dicta incidunt",
154
+ "completed": true
155
+ },
156
+ {
157
+ "userId": 2,
158
+ "id": 36,
159
+ "title": "excepturi deleniti adipisci voluptatem et neque optio illum ad",
160
+ "completed": true
161
+ },
162
+ {
163
+ "userId": 2,
164
+ "id": 37,
165
+ "title": "sunt cum tempora",
166
+ "completed": false
167
+ },
168
+ {
169
+ "userId": 2,
170
+ "id": 38,
171
+ "title": "totam quia non",
172
+ "completed": false
173
+ },
174
+ {
175
+ "userId": 2,
176
+ "id": 39,
177
+ "title": "doloremque quibusdam asperiores libero corrupti illum qui omnis",
178
+ "completed": false
179
+ },
180
+ {
181
+ "userId": 2,
182
+ "id": 40,
183
+ "title": "totam atque quo nesciunt",
184
+ "completed": true
185
+ }
186
+ ]
187
+ http_version:
188
+ recorded_at: Wed, 17 Apr 2019 18:24:07 GMT
189
+ recorded_with: VCR 3.0.3
data/spec/support/stub.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Support
2
2
  module Stub
3
- def stub_api(root)
3
+ def stub_api(root, params = {})
4
4
  ApiStruct::Settings.configure do |config|
5
- config.endpoints = { stub_api: { root: root } }
5
+ config.endpoints = { stub_api: { root: root, params: params } }
6
6
  end
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - bezrukavyi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2018-11-27 00:00:00.000000000 Z
13
+ date: 2019-06-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: dry-monads
@@ -40,6 +40,20 @@ dependencies:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: 0.7.0
43
+ - !ruby/object:Gem::Dependency
44
+ name: dry-inflector
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.1.2
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: 0.1.2
43
57
  - !ruby/object:Gem::Dependency
44
58
  name: http
45
59
  requirement: !ruby/object:Gem::Requirement
@@ -243,6 +257,7 @@ files:
243
257
  - spec/fixtures/cassettes/posts/suffix.yml
244
258
  - spec/fixtures/cassettes/posts/update_success.yml
245
259
  - spec/fixtures/cassettes/todos.yml
260
+ - spec/fixtures/cassettes/user_todos.yml
246
261
  - spec/fixtures/cassettes/users/1/posts.yml
247
262
  - spec/fixtures/cassettes/users/1/posts/1.yml
248
263
  - spec/spec_helper.rb