ddy_remote_resource 1.0.5 → 1.2.1

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
  SHA256:
3
- metadata.gz: fe4c10288f80776d4eca63eb7f5f7db427b470d549e2050cef173a1719432e10
4
- data.tar.gz: c6d661086f88ec0f9efd0b2c185f46824cfc9bbad46ae98a04db990907457a3c
3
+ metadata.gz: 72cede4abb216272f1f22c2e8c2509bc832a77ecfc1b10435c462206f56294de
4
+ data.tar.gz: d4fb9fa5d7515de365d5115e9652c27ece767f588ac99f458cb6cb367af947f0
5
5
  SHA512:
6
- metadata.gz: 74d865281d9c94853ceff853318242bd412f34bacd33cb35c1aec4dbb3d02c55cee46a0cd412dd2fa9b6b903efaae7a339cd988a803436f6ba765510d0649022
7
- data.tar.gz: cb9220f100cb61250b34f64c9368966aa300bf364a402d754b83b00f10ec78b95295b3274ce1e235bd37fbdebc3b959f0e311478aed153e7b9528308f8053006
6
+ metadata.gz: 518d4d673aed4390fc3b46bf190905da19566b31e86f2d20b82b7cc3efa1f4120244d69b6aaf2dafd2aecc6e90529df0362864b53511d218406d85ea33a8db98
7
+ data.tar.gz: 07621f0c66b4efb19536e34a08ca6a38ed3ae8bf2e760843363ff2ab9e0fcb8c5cf0b1b5626063856710378bfc09ca40f06f58d421e44a02fa432b547dc7cd7a
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .idea/
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.5.3
data/.travis.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.1
3
+ - 2.5.3
@@ -23,6 +23,7 @@ module RemoteResource
23
23
  attr_writer :destroyed, :persisted, :success
24
24
 
25
25
  class_attribute :root_element, instance_accessor: false
26
+ class_attribute :json_spec, instance_accessor: false
26
27
 
27
28
  attribute :id
28
29
  end
@@ -1,7 +1,7 @@
1
1
  module RemoteResource
2
2
  class ConnectionOptions
3
3
 
4
- AVAILABLE_OPTIONS = [:site, :headers, :default_headers, :version, :path_prefix, :path_postfix, :collection_prefix, :extension, :collection, :collection_name, :root_element].freeze
4
+ AVAILABLE_OPTIONS = [:site, :headers, :default_headers, :version, :path_prefix, :path_postfix, :collection_prefix, :extension, :collection, :collection_name, :root_element, :json_spec].freeze
5
5
 
6
6
  attr_reader :base_class
7
7
 
@@ -14,6 +14,9 @@ module RemoteResource
14
14
 
15
15
  DEFAULT_EXTENSION = '.json'.freeze
16
16
 
17
+ DEFAULT_CONNECT_TIMEOUT = 30
18
+ DEFAULT_READ_TIMEOUT = 120
19
+
17
20
  attr_reader :resource, :resource_klass, :http_action, :attributes
18
21
 
19
22
  def initialize(resource, http_action, attributes = {}, connection_options = {})
@@ -41,7 +44,7 @@ module RemoteResource
41
44
  def perform
42
45
  SUPPORTED_HTTP_METHODS.include?(http_action) || raise(RemoteResource::HTTPMethodUnsupported, "Requested HTTP method=#{http_action.to_s} is NOT supported, the HTTP action MUST be a supported HTTP action=#{SUPPORTED_HTTP_METHODS.join(', ')}")
43
46
 
44
- connection_response = connection.public_send(http_action, request_url, params: query, body: body, headers: headers)
47
+ connection_response = connection.public_send(http_action, request_url, params: query, body: body, headers: headers, **timeout_options)
45
48
  response = RemoteResource::Response.new(connection_response, connection_options.merge(request: self, connection_request: connection_response.request))
46
49
 
47
50
  if response.success? || response.unprocessable_entity?
@@ -76,7 +79,7 @@ module RemoteResource
76
79
  def body
77
80
  @body ||= begin
78
81
  if [:put, :patch, :post].include?(http_action)
79
- JSON.generate(attributes)
82
+ attributes.to_json
80
83
  else
81
84
  nil
82
85
  end
@@ -84,12 +87,20 @@ module RemoteResource
84
87
  end
85
88
 
86
89
  def attributes
87
- root_element = connection_options[:root_element]
88
-
89
- if root_element.present?
90
- { root_element => @attributes }
90
+ if connection_options[:json_spec] == :json_api
91
+ if @attributes
92
+ { data: { id: @attributes[:id], type: resource_klass.name.demodulize, attributes: @attributes.except(:id) } }
93
+ else
94
+ { data: {} }
95
+ end
91
96
  else
92
- @attributes || {}
97
+ root_element = connection_options[:root_element]
98
+
99
+ if root_element.present?
100
+ { root_element => @attributes }
101
+ else
102
+ @attributes || {}
103
+ end
93
104
  end
94
105
  end
95
106
 
@@ -110,29 +121,58 @@ module RemoteResource
110
121
  headers
111
122
  end
112
123
 
124
+ def timeout_options
125
+ connecttimeout = connection_options[:connecttimeout].presence || DEFAULT_CONNECT_TIMEOUT
126
+ timeout = connection_options[:timeout].presence || DEFAULT_READ_TIMEOUT
127
+
128
+ { connecttimeout: connecttimeout, timeout: timeout }
129
+ end
130
+
113
131
  private
114
132
 
115
133
  def raise_http_error(request, response)
134
+ # Special case if a request has a time out, as Typhoeus does not set a 408 response_code
135
+ raise RemoteResource::HTTPRequestTimeout.new(request, response) if response.timed_out?
136
+
116
137
  case response.try(:response_code)
117
- when 301, 302, 303, 307 then raise RemoteResource::HTTPRedirectionError.new(request, response)
118
- when 400 then raise RemoteResource::HTTPBadRequest.new(request, response)
119
- when 401 then raise RemoteResource::HTTPUnauthorized.new(request, response)
120
- when 403 then raise RemoteResource::HTTPForbidden.new(request, response)
121
- when 404 then raise RemoteResource::HTTPNotFound.new(request, response)
122
- when 405 then raise RemoteResource::HTTPMethodNotAllowed.new(request, response)
123
- when 406 then raise RemoteResource::HTTPNotAcceptable.new(request, response)
124
- when 408 then raise RemoteResource::HTTPRequestTimeout.new(request, response)
125
- when 409 then raise RemoteResource::HTTPConflict.new(request, response)
126
- when 410 then raise RemoteResource::HTTPGone.new(request, response)
127
- when 418 then raise RemoteResource::HTTPTeapot.new(request, response)
128
- when 444 then raise RemoteResource::HTTPNoResponse.new(request, response)
129
- when 494 then raise RemoteResource::HTTPRequestHeaderTooLarge.new(request, response)
130
- when 495 then raise RemoteResource::HTTPCertError.new(request, response)
131
- when 496 then raise RemoteResource::HTTPNoCert.new(request, response)
132
- when 497 then raise RemoteResource::HTTPToHTTPS.new(request, response)
133
- when 499 then raise RemoteResource::HTTPClientClosedRequest.new(request, response)
134
- when 400..499 then raise RemoteResource::HTTPClientError.new(request, response)
135
- when 500..599 then raise RemoteResource::HTTPServerError.new(request, response)
138
+ when 301, 302, 303, 307 then
139
+ raise RemoteResource::HTTPRedirectionError.new(request, response)
140
+ when 400
141
+ raise RemoteResource::HTTPBadRequest.new(request, response)
142
+ when 401
143
+ raise RemoteResource::HTTPUnauthorized.new(request, response)
144
+ when 403
145
+ raise RemoteResource::HTTPForbidden.new(request, response)
146
+ when 404
147
+ raise RemoteResource::HTTPNotFound.new(request, response)
148
+ when 405
149
+ raise RemoteResource::HTTPMethodNotAllowed.new(request, response)
150
+ when 406
151
+ raise RemoteResource::HTTPNotAcceptable.new(request, response)
152
+ when 408
153
+ raise RemoteResource::HTTPRequestTimeout.new(request, response)
154
+ when 409
155
+ raise RemoteResource::HTTPConflict.new(request, response)
156
+ when 410
157
+ raise RemoteResource::HTTPGone.new(request, response)
158
+ when 418
159
+ raise RemoteResource::HTTPTeapot.new(request, response)
160
+ when 444
161
+ raise RemoteResource::HTTPNoResponse.new(request, response)
162
+ when 494
163
+ raise RemoteResource::HTTPRequestHeaderTooLarge.new(request, response)
164
+ when 495
165
+ raise RemoteResource::HTTPCertError.new(request, response)
166
+ when 496
167
+ raise RemoteResource::HTTPNoCert.new(request, response)
168
+ when 497
169
+ raise RemoteResource::HTTPToHTTPS.new(request, response)
170
+ when 499
171
+ raise RemoteResource::HTTPClientClosedRequest.new(request, response)
172
+ when 400..499
173
+ raise RemoteResource::HTTPClientError.new(request, response)
174
+ when 500..599
175
+ raise RemoteResource::HTTPServerError.new(request, response)
136
176
  else
137
177
  raise RemoteResource::HTTPError.new(request, response)
138
178
  end
@@ -16,6 +16,10 @@ module RemoteResource
16
16
  @connection_response.success?
17
17
  end
18
18
 
19
+ def timed_out?
20
+ @connection_response.timed_out?
21
+ end
22
+
19
23
  def unprocessable_entity?
20
24
  response_code == 422
21
25
  end
@@ -44,19 +48,29 @@ module RemoteResource
44
48
 
45
49
  def attributes
46
50
  @attributes ||= begin
47
- root_element = @connection_options[:root_element].to_s
48
- data = nil
49
-
50
- if root_element.present?
51
- data = parsed_body.try(:key?, root_element) && parsed_body[root_element]
51
+ if @connection_options[:json_spec] == :json_api
52
+ data = parsed_body.fetch("data", {})
53
+ if data.is_a?(Array)
54
+ data.map { |row| row["attributes"].merge({ "id" => row["id"] }) }
55
+ elsif data.key?("attributes")
56
+ data["attributes"].merge({ "id" => data["id"] })
57
+ else
58
+ data
59
+ end
52
60
  else
53
- data = parsed_body
54
- end
61
+ root_element = @connection_options[:root_element].to_s
55
62
 
56
- if data.is_a?(Array)
57
- data
58
- else
59
- data.presence || {}
63
+ if root_element.present?
64
+ data = parsed_body.try(:key?, root_element) && parsed_body[root_element]
65
+ else
66
+ data = parsed_body
67
+ end
68
+
69
+ if data.is_a?(Array)
70
+ data
71
+ else
72
+ data.presence || {}
73
+ end
60
74
  end
61
75
  end
62
76
  end
@@ -1,3 +1,3 @@
1
1
  module RemoteResource
2
- VERSION = '1.0.5'.freeze
2
+ VERSION = '1.2.1'.freeze
3
3
  end
@@ -6,8 +6,8 @@ require 'remote_resource/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'ddy_remote_resource'
8
8
  spec.version = RemoteResource::VERSION
9
- spec.authors = ['Jan van der Pas']
10
- spec.email = ['jvanderpas@digidentity.eu']
9
+ spec.authors = ['Digidentity', 'Jan van der Pas']
10
+ spec.email = ['development@digidentity.com']
11
11
  spec.summary = %q{RemoteResource, a gem to use resources with REST services.}
12
12
  spec.description = %q{RemoteResource, a gem to use resources with REST services. A replacement for ActiveResource gem.}
13
13
  spec.homepage = ''
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'bundler'
22
22
  spec.add_development_dependency 'rake', '~> 10.4'
23
23
  spec.add_development_dependency 'rspec', '~> 3.1'
24
24
  spec.add_development_dependency 'pry', '~> 0.10'
@@ -27,11 +27,11 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'guard-rspec', '~> 4.7'
28
28
  spec.add_development_dependency 'terminal-notifier-guard', '~> 1.6'
29
29
 
30
- spec.add_runtime_dependency 'activesupport', '>= 4.1', '< 6'
31
- spec.add_runtime_dependency 'activemodel', '>= 4.1', '< 6'
30
+ spec.add_runtime_dependency 'activesupport', '>= 4.1', '< 7'
31
+ spec.add_runtime_dependency 'activemodel', '>= 4.1', '< 7'
32
32
  spec.add_runtime_dependency 'virtus', '~> 1.0', '>= 1.0.4'
33
33
  spec.add_runtime_dependency 'mime-types', '~> 3.0'
34
- spec.add_runtime_dependency 'ethon', '~> 0.7', '>= 0.7.1'
35
- spec.add_runtime_dependency 'typhoeus', '~> 0.7', '>= 0.7.0'
34
+ spec.add_runtime_dependency 'ethon'
35
+ spec.add_runtime_dependency 'typhoeus', '>= 0.7'
36
36
  spec.add_runtime_dependency 'request_store', '~> 1.4.1'
37
37
  end
@@ -44,7 +44,7 @@ RSpec.describe '.create' do
44
44
 
45
45
  let!(:expected_request) do
46
46
  mock_request = stub_request(:post, 'https://www.example.com/posts.json')
47
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers)
47
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers)
48
48
  mock_request.to_return(status: 201, body: JSON.generate(response_body))
49
49
  mock_request
50
50
  end
@@ -81,7 +81,7 @@ RSpec.describe '.create' do
81
81
 
82
82
  let!(:expected_request) do
83
83
  mock_request = stub_request(:post, 'https://www.example.com/posts.json')
84
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
84
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
85
85
  mock_request.to_return(status: 201, body: JSON.generate(response_body))
86
86
  mock_request
87
87
  end
@@ -114,7 +114,7 @@ RSpec.describe '.create' do
114
114
 
115
115
  let!(:expected_request) do
116
116
  mock_request = stub_request(:post, 'https://www.example.com/posts.json')
117
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers)
117
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers)
118
118
  mock_request.to_return(status: 422, body: JSON.generate(response_body))
119
119
  mock_request
120
120
  end
@@ -48,7 +48,7 @@ RSpec.describe '#save' do
48
48
  describe 'default behaviour' do
49
49
  let!(:expected_request) do
50
50
  mock_request = stub_request(:patch, 'https://www.example.com/posts/12.json')
51
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers)
51
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers)
52
52
  mock_request.to_return(status: 200, body: JSON.generate(response_body))
53
53
  mock_request
54
54
  end
@@ -77,7 +77,7 @@ RSpec.describe '#save' do
77
77
  describe 'with connection_options[:headers]' do
78
78
  let!(:expected_request) do
79
79
  mock_request = stub_request(:patch, 'https://www.example.com/posts/12.json')
80
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
80
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
81
81
  mock_request.to_return(status: 200, body: JSON.generate(response_body))
82
82
  mock_request
83
83
  end
@@ -111,7 +111,7 @@ RSpec.describe '#save' do
111
111
 
112
112
  let!(:expected_request) do
113
113
  mock_request = stub_request(:patch, 'https://www.example.com/posts/12.json')
114
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers)
114
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers)
115
115
  mock_request.to_return(status: 422, body: JSON.generate(response_body))
116
116
  mock_request
117
117
  end
@@ -148,7 +148,7 @@ RSpec.describe '#save' do
148
148
  describe 'with a 500 response' do
149
149
  let!(:expected_request) do
150
150
  mock_request = stub_request(:patch, 'https://www.example.com/posts/12.json')
151
- mock_request.with(query: nil, body: JSON.generate(expected_request_body), headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
151
+ mock_request.with(query: nil, body: expected_request_body.to_json, headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
152
152
  mock_request.to_return(status: 500)
153
153
  mock_request
154
154
  end
@@ -24,7 +24,7 @@ RSpec.describe RemoteResource::ConnectionOptions do
24
24
  end
25
25
 
26
26
  let(:dummy_class) { RemoteResource::ConnectionOptionsDummy }
27
- let(:dummy) { dummy_class.new }
27
+ let(:dummy) { dummy_class.new }
28
28
 
29
29
  let(:connection_options) { described_class.new dummy_class }
30
30
 
@@ -59,8 +59,8 @@ RSpec.describe RemoteResource::ConnectionOptions do
59
59
  describe '#merge' do
60
60
  let(:custom_connection_options) do
61
61
  {
62
- site: 'https://dummy.foobar.com',
63
- version: '/api/v2',
62
+ site: 'https://dummy.foobar.com',
63
+ version: '/api/v2',
64
64
  root_element: :test_dummy_api
65
65
  }
66
66
  end
@@ -91,7 +91,8 @@ RSpec.describe RemoteResource::ConnectionOptions do
91
91
  collection_prefix: '/parent/:parent_id',
92
92
  collection: true,
93
93
  collection_name: nil,
94
- root_element: :test_dummy
94
+ root_element: :test_dummy,
95
+ json_spec: nil
95
96
  }
96
97
  end
97
98
 
@@ -18,10 +18,10 @@ RSpec.describe RemoteResource::Request do
18
18
  end
19
19
 
20
20
  let(:dummy_class) { RemoteResource::RequestDummy }
21
- let(:dummy) { dummy_class.new id: '12' }
21
+ let(:dummy) { dummy_class.new id: '12' }
22
22
 
23
- let(:resource) { dummy_class }
24
- let(:http_action) { :get }
23
+ let(:resource) { dummy_class }
24
+ let(:http_action) { :get }
25
25
  let(:connection_options) { {} }
26
26
  let(:attributes) do
27
27
  { name: 'Mies' }
@@ -68,6 +68,7 @@ RSpec.describe RemoteResource::Request do
68
68
 
69
69
  let(:block_connection_options) do
70
70
  {
71
+ json_spec: 'From .with_connection_options',
71
72
  root_element: 'From .with_connection_options',
72
73
  version: 'From .with_connection_options',
73
74
  path_prefix: 'From .with_connection_options'
@@ -85,6 +86,7 @@ RSpec.describe RemoteResource::Request do
85
86
  {
86
87
  site: 'From Klass.site',
87
88
  root_element: 'From connection_options[]',
89
+ json_spec: 'From .with_connection_options',
88
90
  version: 'From .with_connection_options',
89
91
  path_prefix: 'From .with_connection_options',
90
92
  path_postfix: 'From connection_options[]',
@@ -166,7 +168,9 @@ RSpec.describe RemoteResource::Request do
166
168
  let(:expected_connection_options) { request.connection_options }
167
169
 
168
170
  it 'makes a GET request with the connection_options[:params] as query' do
169
- expect(connection).to receive(:get).with(expected_request_url, params: expected_params, body: expected_body, headers: expected_headers).and_call_original
171
+ expect(connection).to receive(:get).with(expected_request_url, params: expected_params,
172
+ body: expected_body, headers: expected_headers,
173
+ connecttimeout: 30, timeout: 120).and_call_original
170
174
  request.perform
171
175
  end
172
176
 
@@ -189,7 +193,9 @@ RSpec.describe RemoteResource::Request do
189
193
  let(:expected_connection_options) { request.connection_options }
190
194
 
191
195
  it 'makes a PUT request with the attributes as body' do
192
- expect(connection).to receive(:put).with(expected_request_url, params: expected_params, body: expected_body, headers: expected_headers).and_call_original
196
+ expect(connection).to receive(:put).with(expected_request_url, params: expected_params,
197
+ body: expected_body, headers: expected_headers,
198
+ connecttimeout: 30, timeout: 120).and_call_original
193
199
  request.perform
194
200
  end
195
201
 
@@ -212,7 +218,9 @@ RSpec.describe RemoteResource::Request do
212
218
  let(:expected_connection_options) { request.connection_options }
213
219
 
214
220
  it 'makes a PATCH request with the attributes as body' do
215
- expect(connection).to receive(:patch).with(expected_request_url, params: expected_params, body: expected_body, headers: expected_headers).and_call_original
221
+ expect(connection).to receive(:patch).with(expected_request_url, params: expected_params,
222
+ body: expected_body, headers: expected_headers,
223
+ connecttimeout: 30, timeout: 120).and_call_original
216
224
  request.perform
217
225
  end
218
226
 
@@ -235,7 +243,9 @@ RSpec.describe RemoteResource::Request do
235
243
  let(:expected_connection_options) { request.connection_options }
236
244
 
237
245
  it 'makes a POST request with the attributes as body' do
238
- expect(connection).to receive(:post).with(expected_request_url, params: expected_params, body: expected_body, headers: expected_headers).and_call_original
246
+ expect(connection).to receive(:post).with(expected_request_url, params: expected_params,
247
+ body: expected_body, headers: expected_headers,
248
+ connecttimeout: 30, timeout: 120).and_call_original
239
249
  request.perform
240
250
  end
241
251
 
@@ -258,7 +268,9 @@ RSpec.describe RemoteResource::Request do
258
268
  let(:expected_connection_options) { request.connection_options }
259
269
 
260
270
  it 'makes a DELETE request with the connection_options[:params] as query' do
261
- expect(connection).to receive(:delete).with(expected_request_url, params: expected_params, body: expected_body, headers: expected_headers).and_call_original
271
+ expect(connection).to receive(:delete).with(expected_request_url, params: expected_params,
272
+ body: expected_body, headers: expected_headers,
273
+ connecttimeout: 30, timeout: 120).and_call_original
262
274
  request.perform
263
275
  end
264
276
 
@@ -270,7 +282,7 @@ RSpec.describe RemoteResource::Request do
270
282
  let(:expected_request_url) { '' }
271
283
 
272
284
  it 'raises the RemoteResource::HTTPMethodUnsupported error' do
273
- expect{ request.perform }.to raise_error RemoteResource::HTTPMethodUnsupported, 'Requested HTTP method=foo is NOT supported, the HTTP action MUST be a supported HTTP action=get, put, patch, post, delete'
285
+ expect { request.perform }.to raise_error RemoteResource::HTTPMethodUnsupported, 'Requested HTTP method=foo is NOT supported, the HTTP action MUST be a supported HTTP action=get, put, patch, post, delete'
274
286
  end
275
287
  end
276
288
  end
@@ -367,7 +379,7 @@ RSpec.describe RemoteResource::Request do
367
379
 
368
380
  context 'when connection_options does NOT include collection_options' do
369
381
  it 'raises error' do
370
- expect{ request.request_url }.to raise_error(RemoteResource::CollectionOptionKeyError)
382
+ expect { request.request_url }.to raise_error(RemoteResource::CollectionOptionKeyError)
371
383
  end
372
384
  end
373
385
  end
@@ -473,6 +485,30 @@ RSpec.describe RemoteResource::Request do
473
485
  end
474
486
  end
475
487
  end
488
+
489
+ context 'when connection_options[:json_spec] == :json_api' do
490
+ let(:connection_options) do
491
+ { json_spec: :json_api }
492
+ end
493
+
494
+ let(:attributes) do
495
+ { id: 1, name: 'Mies', featured: true, labels: [1, '2', 'three'] }
496
+ end
497
+
498
+ it 'returns the given attributes wrapped in the json api spec' do
499
+ expect(request.attributes).to eql({ data: { id: 1, type: "RequestDummy", attributes: { name: 'Mies', featured: true, labels: [1, '2', 'three'] } } })
500
+ end
501
+
502
+ context 'and there are NO given attributes' do
503
+ let(:attributes) do
504
+ nil
505
+ end
506
+
507
+ it 'returns nil wrapped in the connection_options[:root_element]' do
508
+ expect(request.attributes).to eql({ data: {} })
509
+ end
510
+ end
511
+ end
476
512
  end
477
513
 
478
514
  describe '#headers' do
@@ -506,7 +542,7 @@ RSpec.describe RemoteResource::Request do
506
542
  end
507
543
 
508
544
  before { RemoteResource::Base.global_headers = { 'User-Agent' => 'From RemoteResource::Base.global_headers', 'X-Locale' => 'From RemoteResource::Base.global_headers' } }
509
- after { RemoteResource::Base.global_headers = nil }
545
+ after { RemoteResource::Base.global_headers = nil }
510
546
 
511
547
  it 'returns the default headers while overwriting the headers according to the correct precedence' do
512
548
  expect(request.headers).to eql expected_headers
@@ -560,9 +596,36 @@ RSpec.describe RemoteResource::Request do
560
596
  end
561
597
  end
562
598
 
599
+ describe '#timeout_options' do
600
+ it 'is not given by default' do
601
+ expect(request.connection_options).not_to include :connecttimeout, :timeout
602
+ end
603
+
604
+ context 'with custom timeouts' do
605
+ let(:connection_options) do
606
+ { connecttimeout: 1, timeout: 2 }
607
+ end
608
+
609
+ it 'sets the timeouts from connection_options' do
610
+ aggregate_failures do
611
+ expect(request.connection_options[:connecttimeout]).to eq 1
612
+ expect(request.connection_options[:timeout]).to eq 2
613
+ end
614
+ end
615
+ end
616
+ end
617
+
563
618
  describe '#raise_http_error' do
564
- let(:connection_response) { instance_double(Typhoeus::Response, request: instance_double(Typhoeus::Request)) }
565
- let(:response) { RemoteResource::Response.new(connection_response, connection_options) }
619
+ let(:connection_response) { instance_double(Typhoeus::Response, request: instance_double(Typhoeus::Request), timed_out?: false) }
620
+ let(:response) { RemoteResource::Response.new(connection_response, connection_options) }
621
+
622
+ context 'when the response has timed out' do
623
+ let(:connection_response) { instance_double(Typhoeus::Response, request: instance_double(Typhoeus::Request), timed_out?: true) }
624
+
625
+ it 'raises a RemoteResource::HTTPRequestTimeout' do
626
+ expect { request.send(:raise_http_error, request, response) }.to raise_error RemoteResource::HTTPRequestTimeout
627
+ end
628
+ end
566
629
 
567
630
  context 'when the response code is 301, 302, 303 or 307' do
568
631
  response_codes = [301, 302, 303, 307]
@@ -14,14 +14,14 @@ RSpec.describe RemoteResource::Response do
14
14
  end
15
15
 
16
16
  let(:dummy_class) { RemoteResource::ResponseDummy }
17
- let(:dummy) { dummy_class.new(id: '12') }
17
+ let(:dummy) { dummy_class.new(id: '12') }
18
18
 
19
19
  let(:connection_options) do
20
20
  { collection: true }
21
21
  end
22
- let(:request) { RemoteResource::Request.new(dummy_class, :post, { name: 'Mies' }, connection_options) }
22
+ let(:request) { RemoteResource::Request.new(dummy_class, :post, { name: 'Mies' }, connection_options) }
23
23
  let(:connection_response) { Typhoeus::Response.new(mock: true, code: 201, body: { id: 12, name: 'Mies' }.to_json, headers: { 'Content-Type' => 'application/json', 'Server' => 'nginx/1.4.6 (Ubuntu)' }) }
24
- let(:connection_request) { Typhoeus::Request.new('http://www.foobar.com/response_dummies.json', method: :post, body: { name: 'Mies' }.to_json, headers: { 'Content-Type' => 'application/json' }) }
24
+ let(:connection_request) { Typhoeus::Request.new('http://www.foobar.com/response_dummies.json', method: :post, body: { name: 'Mies' }.to_json, headers: { 'Content-Type' => 'application/json' }) }
25
25
 
26
26
  let(:response) { described_class.new(connection_response, connection_options.merge(request: request, connection_request: connection_request)) }
27
27
 
@@ -156,6 +156,36 @@ RSpec.describe RemoteResource::Response do
156
156
  expect(response.attributes).to eql({})
157
157
  end
158
158
  end
159
+
160
+ context 'with the json_api spec' do
161
+ let(:connection_options) do
162
+ { root_element: :data, json_spec: :json_api }
163
+ end
164
+
165
+ context "single response" do
166
+ let(:connection_response) { Typhoeus::Response.new(mock: true, code: 201, body: { data: { id: 12, attributes: { name: 'Mies' } } }.to_json, headers: { 'Content-Type' => 'application/json', 'Server' => 'nginx/1.4.6 (Ubuntu)' }) }
167
+
168
+ it 'parses the attributes from the nested hash' do
169
+ expect(response.attributes).to eql({ 'id' => 12, 'name' => 'Mies' })
170
+ end
171
+ end
172
+
173
+ context "empty response" do
174
+ let(:connection_response) { Typhoeus::Response.new(mock: true, code: 204, body: {}.to_json, headers: { 'Content-Type' => 'application/json', 'Server' => 'nginx/1.4.6 (Ubuntu)' }) }
175
+
176
+ it 'parses the attributes from the nested hash' do
177
+ expect(response.attributes).to eql({})
178
+ end
179
+ end
180
+
181
+ context "collection response" do
182
+ let(:connection_response) { Typhoeus::Response.new(mock: true, code: 201, body: { data: [{ id: 12, attributes: { name: 'Mies' } }] }.to_json, headers: { 'Content-Type' => 'application/json', 'Server' => 'nginx/1.4.6 (Ubuntu)' }) }
183
+
184
+ it 'parses the attributes from the nested hash' do
185
+ expect(response.attributes).to eql(['id' => 12, 'name' => 'Mies'])
186
+ end
187
+ end
188
+ end
159
189
  end
160
190
 
161
191
  describe '#errors' do
@@ -1,7 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RemoteResource::VERSION do
4
- it { is_expected.to eql '1.0.5' }
4
+ it { is_expected.to eql '1.2.0' }
5
5
  end
6
-
7
-
metadata CHANGED
@@ -1,29 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddy_remote_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
+ - Digidentity
7
8
  - Jan van der Pas
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2018-11-13 00:00:00.000000000 Z
12
+ date: 2021-05-10 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '1.6'
20
+ version: '0'
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - "~>"
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '1.6'
27
+ version: '0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rake
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -117,7 +118,7 @@ dependencies:
117
118
  version: '4.1'
118
119
  - - "<"
119
120
  - !ruby/object:Gem::Version
120
- version: '6'
121
+ version: '7'
121
122
  type: :runtime
122
123
  prerelease: false
123
124
  version_requirements: !ruby/object:Gem::Requirement
@@ -127,7 +128,7 @@ dependencies:
127
128
  version: '4.1'
128
129
  - - "<"
129
130
  - !ruby/object:Gem::Version
130
- version: '6'
131
+ version: '7'
131
132
  - !ruby/object:Gem::Dependency
132
133
  name: activemodel
133
134
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +138,7 @@ dependencies:
137
138
  version: '4.1'
138
139
  - - "<"
139
140
  - !ruby/object:Gem::Version
140
- version: '6'
141
+ version: '7'
141
142
  type: :runtime
142
143
  prerelease: false
143
144
  version_requirements: !ruby/object:Gem::Requirement
@@ -147,7 +148,7 @@ dependencies:
147
148
  version: '4.1'
148
149
  - - "<"
149
150
  - !ruby/object:Gem::Version
150
- version: '6'
151
+ version: '7'
151
152
  - !ruby/object:Gem::Dependency
152
153
  name: virtus
153
154
  requirement: !ruby/object:Gem::Requirement
@@ -186,42 +187,30 @@ dependencies:
186
187
  name: ethon
187
188
  requirement: !ruby/object:Gem::Requirement
188
189
  requirements:
189
- - - "~>"
190
- - !ruby/object:Gem::Version
191
- version: '0.7'
192
190
  - - ">="
193
191
  - !ruby/object:Gem::Version
194
- version: 0.7.1
192
+ version: '0'
195
193
  type: :runtime
196
194
  prerelease: false
197
195
  version_requirements: !ruby/object:Gem::Requirement
198
196
  requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '0.7'
202
197
  - - ">="
203
198
  - !ruby/object:Gem::Version
204
- version: 0.7.1
199
+ version: '0'
205
200
  - !ruby/object:Gem::Dependency
206
201
  name: typhoeus
207
202
  requirement: !ruby/object:Gem::Requirement
208
203
  requirements:
209
- - - "~>"
210
- - !ruby/object:Gem::Version
211
- version: '0.7'
212
204
  - - ">="
213
205
  - !ruby/object:Gem::Version
214
- version: 0.7.0
206
+ version: '0.7'
215
207
  type: :runtime
216
208
  prerelease: false
217
209
  version_requirements: !ruby/object:Gem::Requirement
218
210
  requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: '0.7'
222
211
  - - ">="
223
212
  - !ruby/object:Gem::Version
224
- version: 0.7.0
213
+ version: '0.7'
225
214
  - !ruby/object:Gem::Dependency
226
215
  name: request_store
227
216
  requirement: !ruby/object:Gem::Requirement
@@ -239,7 +228,7 @@ dependencies:
239
228
  description: RemoteResource, a gem to use resources with REST services. A replacement
240
229
  for ActiveResource gem.
241
230
  email:
242
- - jvanderpas@digidentity.eu
231
+ - development@digidentity.com
243
232
  executables: []
244
233
  extensions: []
245
234
  extra_rdoc_files: []
@@ -319,8 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
308
  - !ruby/object:Gem::Version
320
309
  version: '0'
321
310
  requirements: []
322
- rubyforge_project:
323
- rubygems_version: 2.7.7
311
+ rubygems_version: 3.2.15
324
312
  signing_key:
325
313
  specification_version: 4
326
314
  summary: RemoteResource, a gem to use resources with REST services.