ddy_remote_resource 0.4.11 → 1.0.0.rc1
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 +4 -4
- data/Gemfile +2 -0
- data/Guardfile +3 -0
- data/lib/remote_resource.rb +77 -34
- data/lib/remote_resource/base.rb +20 -8
- data/lib/remote_resource/connection.rb +26 -5
- data/lib/remote_resource/connection_options.rb +5 -3
- data/lib/remote_resource/querying/finder_methods.rb +3 -3
- data/lib/remote_resource/querying/persistence_methods.rb +17 -12
- data/lib/remote_resource/request.rb +96 -62
- data/lib/remote_resource/response.rb +5 -1
- data/lib/remote_resource/rest.rb +13 -17
- data/lib/remote_resource/url_naming.rb +4 -10
- data/lib/remote_resource/url_naming_determination.rb +1 -3
- data/lib/remote_resource/util.rb +64 -0
- data/lib/remote_resource/version.rb +1 -1
- data/remote_resource.gemspec +2 -2
- data/spec/fixtures/text_file.txt +1 -0
- data/spec/integration/all_spec.rb +166 -0
- data/spec/integration/collection_prefix_spec.rb +99 -0
- data/spec/integration/create_spec.rb +181 -0
- data/spec/integration/destroy_spec.rb +252 -0
- data/spec/integration/find_by_spec.rb +168 -0
- data/spec/integration/find_spec.rb +139 -0
- data/spec/integration/headers_spec.rb +222 -0
- data/spec/integration/naming_spec.rb +138 -0
- data/spec/integration/save_spec.rb +320 -0
- data/spec/integration/update_attributes_spec.rb +221 -0
- data/spec/integration/where_spec.rb +152 -0
- data/spec/lib/extensions/ethon/easy/queryable_spec.rb +4 -4
- data/spec/lib/remote_resource/base_spec.rb +54 -110
- data/spec/lib/remote_resource/builder_spec.rb +1 -1
- data/spec/lib/remote_resource/collection_spec.rb +1 -1
- data/spec/lib/remote_resource/connection_options_spec.rb +20 -17
- data/spec/lib/remote_resource/connection_spec.rb +36 -27
- data/spec/lib/remote_resource/querying/finder_methods_spec.rb +199 -72
- data/spec/lib/remote_resource/querying/persistence_methods_spec.rb +228 -220
- data/spec/lib/remote_resource/request_spec.rb +313 -342
- data/spec/lib/remote_resource/response_spec.rb +9 -3
- data/spec/lib/remote_resource/rest_spec.rb +11 -11
- data/spec/lib/remote_resource/url_naming_determination_spec.rb +1 -1
- data/spec/lib/remote_resource/url_naming_spec.rb +7 -22
- data/spec/lib/remote_resource/util_spec.rb +56 -0
- data/spec/lib/remote_resource/version_spec.rb +2 -3
- data/spec/spec_helper.rb +37 -0
- metadata +33 -22
- data/lib/remote_resource/http_errors.rb +0 -33
- data/lib/remote_resource/response_handeling.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3d2576b744b3dafd66aff8fca6d991f709fa10d
|
4
|
+
data.tar.gz: b32d6edb8af70dccdfe2b83cf4da340969b7f8b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3934a8a1d740a88e3cae6e8dc726c6af2bbb99bc35c4d8a25faf8ac6993fedcf5cdf67cf9093c9f6cf299b14eba9be50feb89a3527418720b0a8dc5f6e5f264f
|
7
|
+
data.tar.gz: 99b67f28cb4284c6100d69340e3f68020f4e13e3a5abedc99d62242858864b4846e9b207b6c1e79fc0834781e5e04a782cc6372bda5558aa06e29ee7a07d601e
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -40,6 +40,9 @@ guard :rspec, cmd: 'bundle exec rspec', notification: true do
|
|
40
40
|
ruby = dsl.ruby
|
41
41
|
dsl.watch_spec_files_for(ruby.lib_files)
|
42
42
|
|
43
|
+
# Integration specs
|
44
|
+
watch(ruby.lib_files) { 'spec/integration' }
|
45
|
+
|
43
46
|
# Notification (See: https://github.com/Codaisseur/terminal-notifier-guard)
|
44
47
|
notification :terminal_notifier, app_name: 'RemoteResource', activate: 'com.googlecode.iTerm2' if `uname` =~ /Darwin/
|
45
48
|
end
|
data/lib/remote_resource.rb
CHANGED
@@ -17,52 +17,95 @@ require 'remote_resource/rest'
|
|
17
17
|
require 'remote_resource/response'
|
18
18
|
require 'remote_resource/querying/finder_methods'
|
19
19
|
require 'remote_resource/querying/persistence_methods'
|
20
|
-
require 'remote_resource/http_errors'
|
21
20
|
require 'remote_resource/request'
|
22
|
-
|
21
|
+
require 'remote_resource/util'
|
23
22
|
|
24
23
|
module RemoteResource
|
25
|
-
RemoteResourceError = Class.new
|
24
|
+
RemoteResourceError = Class.new(StandardError)
|
26
25
|
|
27
26
|
IdMissingError = Class.new(RemoteResourceError)
|
28
|
-
|
27
|
+
|
29
28
|
CollectionOptionKeyError = Class.new(RemoteResourceError)
|
30
29
|
|
31
|
-
|
30
|
+
HTTPMethodUnsupported = Class.new(RemoteResourceError) # REST action
|
32
31
|
|
33
32
|
class HTTPError < RemoteResourceError # HTTP errors
|
34
33
|
|
35
|
-
def initialize(response)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
def initialize(request, response)
|
35
|
+
@request = request
|
36
|
+
@response = response
|
37
|
+
end
|
38
|
+
|
39
|
+
def resource_klass
|
40
|
+
@request.resource_klass
|
41
|
+
end
|
42
|
+
|
43
|
+
def http_action
|
44
|
+
@request.http_action
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_url
|
48
|
+
@request.request_url
|
49
|
+
end
|
50
|
+
|
51
|
+
def request_query
|
52
|
+
@request.query
|
53
|
+
end
|
54
|
+
|
55
|
+
def request_body
|
56
|
+
@request.body # TODO: Filter sensitive information using: RemoteResource::Util.filter_params
|
57
|
+
end
|
58
|
+
|
59
|
+
def request_headers
|
60
|
+
@request.headers
|
61
|
+
end
|
62
|
+
|
63
|
+
def response_code
|
64
|
+
@response.response_code
|
65
|
+
end
|
66
|
+
|
67
|
+
def response_body
|
68
|
+
@response.response_body # TODO: Filter sensitive information using: RemoteResource::Util.filter_params
|
69
|
+
end
|
70
|
+
|
71
|
+
def response_headers
|
72
|
+
@response.response_headers
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
message = "HTTP request failed for #{resource_klass}"
|
77
|
+
message << " with response_code=#{response_code}" if response_code.present?
|
78
|
+
message << " with http_action=#{http_action}"
|
79
|
+
message << " with request_url=#{request_url}"
|
80
|
+
# message << " with request_query=#{request_query}" if request_query.present? # TODO: Test usability of error message whether to include this
|
81
|
+
# message << " with request_body=#{request_body}" if request_body.present? # TODO: Test usability of error message whether to include this
|
82
|
+
# message << " with response_body=#{response_body}" if response_body.present? # TODO: Test usability of error message whether to include this
|
83
|
+
message
|
41
84
|
end
|
42
85
|
end
|
43
86
|
|
44
|
-
HTTPRedirectionError = Class.new
|
45
|
-
HTTPClientError = Class.new
|
46
|
-
HTTPServerError = Class.new
|
47
|
-
|
48
|
-
HTTPBadRequest
|
49
|
-
HTTPUnauthorized
|
50
|
-
HTTPForbidden
|
51
|
-
HTTPNotFound
|
52
|
-
HTTPMethodNotAllowed
|
53
|
-
HTTPNotAcceptable
|
54
|
-
HTTPRequestTimeout
|
55
|
-
HTTPConflict
|
56
|
-
HTTPGone
|
57
|
-
HTTPTeapot
|
58
|
-
|
59
|
-
NginxClientError = Class.new
|
60
|
-
|
61
|
-
HTTPNoResponse = Class.new
|
62
|
-
HTTPRequestHeaderTooLarge = Class.new
|
63
|
-
HTTPCertError = Class.new
|
64
|
-
HTTPNoCert = Class.new
|
65
|
-
HTTPToHTTPS = Class.new
|
66
|
-
HTTPClientClosedRequest = Class.new
|
87
|
+
HTTPRedirectionError = Class.new(HTTPError) # HTTP 3xx
|
88
|
+
HTTPClientError = Class.new(HTTPError) # HTTP 4xx
|
89
|
+
HTTPServerError = Class.new(HTTPError) # HTTP 5xx
|
90
|
+
|
91
|
+
HTTPBadRequest = Class.new(HTTPClientError) # HTTP 400
|
92
|
+
HTTPUnauthorized = Class.new(HTTPClientError) # HTTP 401
|
93
|
+
HTTPForbidden = Class.new(HTTPClientError) # HTTP 403
|
94
|
+
HTTPNotFound = Class.new(HTTPClientError) # HTTP 404
|
95
|
+
HTTPMethodNotAllowed = Class.new(HTTPClientError) # HTTP 405
|
96
|
+
HTTPNotAcceptable = Class.new(HTTPClientError) # HTTP 406
|
97
|
+
HTTPRequestTimeout = Class.new(HTTPClientError) # HTTP 408
|
98
|
+
HTTPConflict = Class.new(HTTPClientError) # HTTP 409
|
99
|
+
HTTPGone = Class.new(HTTPClientError) # HTTP 410
|
100
|
+
HTTPTeapot = Class.new(HTTPClientError) # HTTP 418
|
101
|
+
|
102
|
+
NginxClientError = Class.new(HTTPClientError) # HTTP errors used in Nginx
|
103
|
+
|
104
|
+
HTTPNoResponse = Class.new(NginxClientError) # HTTP 444
|
105
|
+
HTTPRequestHeaderTooLarge = Class.new(NginxClientError) # HTTP 494
|
106
|
+
HTTPCertError = Class.new(NginxClientError) # HTTP 495
|
107
|
+
HTTPNoCert = Class.new(NginxClientError) # HTTP 496
|
108
|
+
HTTPToHTTPS = Class.new(NginxClientError) # HTTP 497
|
109
|
+
HTTPClientClosedRequest = Class.new(NginxClientError) # HTTP 499
|
67
110
|
|
68
111
|
end
|
data/lib/remote_resource/base.rb
CHANGED
@@ -2,8 +2,6 @@ module RemoteResource
|
|
2
2
|
module Base
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
OPTIONS = [:base_url, :site, :headers, :version, :path_prefix, :path_postfix, :collection_prefix, :content_type, :collection, :collection_name, :root_element]
|
6
|
-
|
7
5
|
included do
|
8
6
|
include Virtus.model
|
9
7
|
extend ActiveModel::Naming
|
@@ -14,12 +12,15 @@ module RemoteResource
|
|
14
12
|
include RemoteResource::Builder
|
15
13
|
include RemoteResource::UrlNaming
|
16
14
|
include RemoteResource::Connection
|
15
|
+
|
16
|
+
extend RemoteResource::REST
|
17
17
|
include RemoteResource::REST
|
18
18
|
|
19
19
|
include RemoteResource::Querying::FinderMethods
|
20
20
|
include RemoteResource::Querying::PersistenceMethods
|
21
21
|
|
22
22
|
attr_accessor :_response
|
23
|
+
attr_accessor :destroyed
|
23
24
|
|
24
25
|
attribute :id
|
25
26
|
class_attribute :root_element, instance_accessor: false
|
@@ -45,8 +46,7 @@ module RemoteResource
|
|
45
46
|
|
46
47
|
def with_connection_options(connection_options = {})
|
47
48
|
begin
|
48
|
-
threaded_connection_options
|
49
|
-
Thread.current[threaded_connection_options_thread_name].merge! connection_options
|
49
|
+
Thread.current[threaded_connection_options_thread_name] = threaded_connection_options.merge(connection_options)
|
50
50
|
yield
|
51
51
|
ensure
|
52
52
|
Thread.current[threaded_connection_options_thread_name] = nil
|
@@ -68,8 +68,16 @@ module RemoteResource
|
|
68
68
|
@connection_options ||= RemoteResource::ConnectionOptions.new(self.class)
|
69
69
|
end
|
70
70
|
|
71
|
+
def persistence
|
72
|
+
self if persisted?
|
73
|
+
end
|
74
|
+
|
71
75
|
def persisted?
|
72
|
-
|
76
|
+
if destroyed
|
77
|
+
false
|
78
|
+
else
|
79
|
+
id.present?
|
80
|
+
end
|
73
81
|
end
|
74
82
|
|
75
83
|
def new_record?
|
@@ -105,11 +113,15 @@ module RemoteResource
|
|
105
113
|
private
|
106
114
|
|
107
115
|
def assign_errors(error_messages)
|
108
|
-
return unless error_messages.respond_to?
|
116
|
+
return unless error_messages.respond_to?(:each)
|
109
117
|
|
110
118
|
error_messages.each do |attribute, attribute_errors|
|
111
|
-
attribute_errors.each do |
|
112
|
-
|
119
|
+
attribute_errors.each do |attribute_error|
|
120
|
+
if respond_to?(attribute)
|
121
|
+
self.errors.add(attribute, attribute_error)
|
122
|
+
else
|
123
|
+
self.errors.add(:base, attribute_error)
|
124
|
+
end
|
113
125
|
end
|
114
126
|
end
|
115
127
|
end
|
@@ -3,10 +3,9 @@ module RemoteResource
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
class_attribute :
|
6
|
+
class_attribute :extension, :default_headers, instance_accessor: false
|
7
7
|
|
8
|
-
self.
|
9
|
-
self.default_headers = { "Accept" => "application/json" }
|
8
|
+
self.default_headers = {}
|
10
9
|
end
|
11
10
|
|
12
11
|
module ClassMethods
|
@@ -15,10 +14,32 @@ module RemoteResource
|
|
15
14
|
Typhoeus::Request
|
16
15
|
end
|
17
16
|
|
17
|
+
def content_type=(content_type)
|
18
|
+
warn '[DEPRECATION] `.content_type=` is deprecated. Please use `.extension=` instead.'
|
19
|
+
self.extension = content_type
|
20
|
+
end
|
21
|
+
|
22
|
+
def content_type
|
23
|
+
warn '[DEPRECATION] `.content_type` is deprecated. Please use `.extension` instead.'
|
24
|
+
self.extension
|
25
|
+
end
|
26
|
+
|
27
|
+
def extra_headers=(_)
|
28
|
+
warn '[DEPRECATION] `.extra_headers=` is deprecated. Please overwrite the .headers method to set custom headers.'
|
29
|
+
end
|
30
|
+
|
31
|
+
def extra_headers
|
32
|
+
warn '[DEPRECATION] `.extra_headers` is deprecated. Please overwrite the .headers method to set custom headers.'
|
33
|
+
end
|
34
|
+
|
35
|
+
def headers=(_)
|
36
|
+
warn '[WARNING] `.headers=` can not be used to set custom headers. Please overwrite the .headers method to set custom headers.'
|
37
|
+
end
|
38
|
+
|
18
39
|
def headers
|
19
|
-
|
40
|
+
{}
|
20
41
|
end
|
21
42
|
|
22
43
|
end
|
23
44
|
end
|
24
|
-
end
|
45
|
+
end
|
@@ -1,6 +1,8 @@
|
|
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
|
5
|
+
|
4
6
|
attr_reader :base_class
|
5
7
|
|
6
8
|
def initialize(base_class)
|
@@ -15,7 +17,7 @@ module RemoteResource
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def to_hash
|
18
|
-
|
20
|
+
AVAILABLE_OPTIONS.each_with_object(Hash.new) do |option, hash|
|
19
21
|
hash[option] = self.public_send option
|
20
22
|
end
|
21
23
|
end
|
@@ -31,11 +33,11 @@ module RemoteResource
|
|
31
33
|
private
|
32
34
|
|
33
35
|
def initialize_connection_options
|
34
|
-
|
36
|
+
AVAILABLE_OPTIONS.each do |option|
|
35
37
|
self.class.send :attr_accessor, option
|
36
38
|
self.public_send "#{option}=", base_class.public_send(option)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
end
|
41
|
-
end
|
43
|
+
end
|
@@ -6,12 +6,12 @@ module RemoteResource
|
|
6
6
|
module ClassMethods
|
7
7
|
|
8
8
|
def find(id, connection_options = {})
|
9
|
-
response = RemoteResource::Request.new(self, :get, {
|
9
|
+
response = RemoteResource::Request.new(self, :get, {}, connection_options.merge(id: id)).perform
|
10
10
|
build_resource_from_response(response)
|
11
11
|
end
|
12
12
|
|
13
13
|
def find_by(params, connection_options = {})
|
14
|
-
response = RemoteResource::Request.new(self, :get, params,
|
14
|
+
response = RemoteResource::Request.new(self, :get, {}, connection_options.deep_merge(id: params[:id], params: params.except(:id))).perform
|
15
15
|
build_resource_from_response(response)
|
16
16
|
end
|
17
17
|
|
@@ -21,7 +21,7 @@ module RemoteResource
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def where(params, connection_options = {})
|
24
|
-
response = RemoteResource::Request.new(self, :get,
|
24
|
+
response = RemoteResource::Request.new(self, :get, {}, connection_options.deep_merge(collection: true, params: params)).perform
|
25
25
|
build_collection_from_response(response)
|
26
26
|
end
|
27
27
|
end
|
@@ -12,9 +12,11 @@ module RemoteResource
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def destroy(id, connection_options = {})
|
15
|
-
resource = new
|
16
|
-
response = RemoteResource::Request.new(self, :delete, {
|
15
|
+
resource = new(id: id)
|
16
|
+
response = RemoteResource::Request.new(self, :delete, {}, connection_options.merge(id: id)).perform
|
17
17
|
resource.handle_response(response)
|
18
|
+
resource.destroyed = resource.success?
|
19
|
+
resource
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -29,22 +31,25 @@ module RemoteResource
|
|
29
31
|
success? ? self : false
|
30
32
|
end
|
31
33
|
|
32
|
-
def create_or_update(attributes = {}, connection_options = {})
|
33
|
-
if attributes.has_key?(:id)
|
34
|
-
response = RemoteResource::Request.new(self, :patch, attributes, connection_options).perform
|
35
|
-
else
|
36
|
-
response = RemoteResource::Request.new(self, :post, attributes, connection_options).perform
|
37
|
-
end
|
38
|
-
handle_response(response)
|
39
|
-
end
|
40
|
-
|
41
34
|
def destroy(connection_options = {})
|
42
35
|
id.present? || raise(RemoteResource::IdMissingError.new("`id` is missing from resource"))
|
43
|
-
response = RemoteResource::Request.new(self, :delete, {
|
36
|
+
response = RemoteResource::Request.new(self, :delete, {}, connection_options.merge(id: id)).perform
|
44
37
|
handle_response(response)
|
38
|
+
self.destroyed = success?
|
45
39
|
success? ? self : false
|
46
40
|
end
|
47
41
|
|
42
|
+
private
|
43
|
+
|
44
|
+
def create_or_update(attributes = {}, connection_options = {})
|
45
|
+
if attributes.has_key?(:id) && attributes[:id].present?
|
46
|
+
response = RemoteResource::Request.new(self, :patch, attributes.except(:id), connection_options.merge(id: attributes[:id])).perform
|
47
|
+
else
|
48
|
+
response = RemoteResource::Request.new(self, :post, attributes.except(:id), connection_options).perform
|
49
|
+
end
|
50
|
+
handle_response(response)
|
51
|
+
end
|
52
|
+
|
48
53
|
end
|
49
54
|
end
|
50
55
|
end
|
@@ -1,15 +1,27 @@
|
|
1
1
|
module RemoteResource
|
2
2
|
class Request
|
3
|
-
include RemoteResource::HTTPErrors
|
4
3
|
|
5
|
-
|
4
|
+
SUPPORTED_HTTP_METHODS = [:get, :put, :patch, :post, :delete].freeze
|
6
5
|
|
7
|
-
|
6
|
+
DEFAULT_HEADERS = {
|
7
|
+
'Accept' => 'application/json',
|
8
|
+
'User-Agent' => "RemoteResource #{RemoteResource::VERSION}"
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
DEFAULT_CONTENT_TYPE = {
|
12
|
+
'Content-Type' => 'application/json'
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
DEFAULT_EXTENSION = '.json'.freeze
|
16
|
+
|
17
|
+
attr_reader :resource, :resource_klass, :http_action, :attributes
|
18
|
+
|
19
|
+
def initialize(resource, http_action, attributes = {}, connection_options = {})
|
8
20
|
@resource = resource
|
9
|
-
@
|
21
|
+
@resource_klass = resource.is_a?(Class) ? resource : resource.class
|
22
|
+
@http_action = http_action.to_sym
|
10
23
|
@attributes = attributes
|
11
|
-
@connection_options = connection_options
|
12
|
-
@original_connection_options = connection_options.dup
|
24
|
+
@connection_options = connection_options.dup
|
13
25
|
end
|
14
26
|
|
15
27
|
def connection
|
@@ -17,90 +29,112 @@ module RemoteResource
|
|
17
29
|
end
|
18
30
|
|
19
31
|
def connection_options
|
20
|
-
@
|
21
|
-
|
32
|
+
@combined_connection_options ||= begin
|
33
|
+
default = resource.connection_options.to_hash # Defined on the resource (klass).
|
34
|
+
block = resource.try(:threaded_connection_options) || {} # Given as arguments in the .with_connection_options block.
|
35
|
+
local = @connection_options # Given as arguments directly.
|
22
36
|
|
23
|
-
|
24
|
-
|
37
|
+
default.deep_merge(block).deep_merge(local)
|
38
|
+
end
|
25
39
|
end
|
26
40
|
|
27
41
|
def perform
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
response = connection.public_send rest_action, determined_request_url, body: determined_attributes, headers: determined_headers
|
33
|
-
when :delete
|
34
|
-
response = connection.public_send rest_action, determined_request_url, params: determined_params, headers: determined_headers
|
35
|
-
else
|
36
|
-
raise RemoteResource::RESTActionUnknown, "for action: '#{rest_action}'"
|
37
|
-
end
|
42
|
+
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
|
+
|
44
|
+
connection_response = connection.public_send(http_action, request_url, params: query, body: body, headers: headers)
|
45
|
+
response = RemoteResource::Response.new(connection_response, connection_options)
|
38
46
|
|
39
|
-
if response.success? || response.
|
40
|
-
|
47
|
+
if response.success? || response.unprocessable_entity?
|
48
|
+
response
|
41
49
|
else
|
42
|
-
|
50
|
+
raise_http_error(self, response)
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
def request_url
|
55
|
+
@request_url ||= begin
|
56
|
+
id = @attributes[:id].presence || connection_options[:id]
|
57
|
+
base_url = connection_options[:base_url].presence || RemoteResource::UrlNamingDetermination.new(resource_klass, connection_options).base_url(id, check_collection_options: true)
|
58
|
+
extension = connection_options[:extension] || DEFAULT_EXTENSION
|
50
59
|
|
51
|
-
|
60
|
+
"#{base_url}#{extension}"
|
61
|
+
end
|
52
62
|
end
|
53
63
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
params = connection_options[:params].presence || {}
|
64
|
+
def query
|
65
|
+
@query ||= begin
|
66
|
+
params = connection_options[:params]
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
attributes.merge! params
|
68
|
+
if params.present?
|
69
|
+
RemoteResource::Util.encode_params_to_query(params)
|
70
|
+
else
|
71
|
+
nil
|
72
|
+
end
|
65
73
|
end
|
66
74
|
end
|
67
75
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
pack_up_attributes attributes, root_element
|
76
|
-
else
|
77
|
-
attributes
|
76
|
+
def body
|
77
|
+
@body ||= begin
|
78
|
+
if [:put, :patch, :post].include?(http_action)
|
79
|
+
JSON.generate(attributes)
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
78
83
|
end
|
79
84
|
end
|
80
85
|
|
81
|
-
def
|
82
|
-
|
86
|
+
def attributes
|
87
|
+
root_element = connection_options[:root_element]
|
83
88
|
|
84
|
-
|
85
|
-
|
89
|
+
if root_element.present?
|
90
|
+
{ root_element => @attributes }
|
91
|
+
else
|
92
|
+
@attributes || {}
|
93
|
+
end
|
86
94
|
end
|
87
95
|
|
88
|
-
|
96
|
+
def headers
|
97
|
+
@headers ||= begin
|
98
|
+
default_headers = connection_options[:default_headers].presence || DEFAULT_HEADERS
|
99
|
+
global_headers = RemoteResource::Base.global_headers.presence || {}
|
100
|
+
headers = connection_options[:headers].presence || {}
|
89
101
|
|
90
|
-
|
91
|
-
|
102
|
+
default_headers.merge(global_headers).merge(headers).merge(conditional_headers)
|
103
|
+
end
|
92
104
|
end
|
93
105
|
|
94
|
-
def
|
95
|
-
|
106
|
+
def conditional_headers
|
107
|
+
headers = {}
|
108
|
+
headers = headers.merge(DEFAULT_CONTENT_TYPE) if body.present?
|
109
|
+
headers
|
96
110
|
end
|
97
111
|
|
98
|
-
|
99
|
-
resource.is_a?(Class) ? resource : resource.class
|
100
|
-
end
|
112
|
+
private
|
101
113
|
|
102
|
-
def
|
103
|
-
|
114
|
+
def raise_http_error(request, response)
|
115
|
+
case response.try(:response_code)
|
116
|
+
when 301, 302, 303, 307 then raise RemoteResource::HTTPRedirectionError.new(request, response)
|
117
|
+
when 400 then raise RemoteResource::HTTPBadRequest.new(request, response)
|
118
|
+
when 401 then raise RemoteResource::HTTPUnauthorized.new(request, response)
|
119
|
+
when 403 then raise RemoteResource::HTTPForbidden.new(request, response)
|
120
|
+
when 404 then raise RemoteResource::HTTPNotFound.new(request, response)
|
121
|
+
when 405 then raise RemoteResource::HTTPMethodNotAllowed.new(request, response)
|
122
|
+
when 406 then raise RemoteResource::HTTPNotAcceptable.new(request, response)
|
123
|
+
when 408 then raise RemoteResource::HTTPRequestTimeout.new(request, response)
|
124
|
+
when 409 then raise RemoteResource::HTTPConflict.new(request, response)
|
125
|
+
when 410 then raise RemoteResource::HTTPGone.new(request, response)
|
126
|
+
when 418 then raise RemoteResource::HTTPTeapot.new(request, response)
|
127
|
+
when 444 then raise RemoteResource::HTTPNoResponse.new(request, response)
|
128
|
+
when 494 then raise RemoteResource::HTTPRequestHeaderTooLarge.new(request, response)
|
129
|
+
when 495 then raise RemoteResource::HTTPCertError.new(request, response)
|
130
|
+
when 496 then raise RemoteResource::HTTPNoCert.new(request, response)
|
131
|
+
when 497 then raise RemoteResource::HTTPToHTTPS.new(request, response)
|
132
|
+
when 499 then raise RemoteResource::HTTPClientClosedRequest.new(request, response)
|
133
|
+
when 400..499 then raise RemoteResource::HTTPClientError.new(request, response)
|
134
|
+
when 500..599 then raise RemoteResource::HTTPServerError.new(request, response)
|
135
|
+
else
|
136
|
+
raise RemoteResource::HTTPError.new(request, response)
|
137
|
+
end
|
104
138
|
end
|
105
139
|
|
106
140
|
end
|