ddy_remote_resource 0.4.11 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Guardfile +3 -0
  4. data/lib/remote_resource.rb +77 -34
  5. data/lib/remote_resource/base.rb +20 -8
  6. data/lib/remote_resource/connection.rb +26 -5
  7. data/lib/remote_resource/connection_options.rb +5 -3
  8. data/lib/remote_resource/querying/finder_methods.rb +3 -3
  9. data/lib/remote_resource/querying/persistence_methods.rb +17 -12
  10. data/lib/remote_resource/request.rb +96 -62
  11. data/lib/remote_resource/response.rb +5 -1
  12. data/lib/remote_resource/rest.rb +13 -17
  13. data/lib/remote_resource/url_naming.rb +4 -10
  14. data/lib/remote_resource/url_naming_determination.rb +1 -3
  15. data/lib/remote_resource/util.rb +64 -0
  16. data/lib/remote_resource/version.rb +1 -1
  17. data/remote_resource.gemspec +2 -2
  18. data/spec/fixtures/text_file.txt +1 -0
  19. data/spec/integration/all_spec.rb +166 -0
  20. data/spec/integration/collection_prefix_spec.rb +99 -0
  21. data/spec/integration/create_spec.rb +181 -0
  22. data/spec/integration/destroy_spec.rb +252 -0
  23. data/spec/integration/find_by_spec.rb +168 -0
  24. data/spec/integration/find_spec.rb +139 -0
  25. data/spec/integration/headers_spec.rb +222 -0
  26. data/spec/integration/naming_spec.rb +138 -0
  27. data/spec/integration/save_spec.rb +320 -0
  28. data/spec/integration/update_attributes_spec.rb +221 -0
  29. data/spec/integration/where_spec.rb +152 -0
  30. data/spec/lib/extensions/ethon/easy/queryable_spec.rb +4 -4
  31. data/spec/lib/remote_resource/base_spec.rb +54 -110
  32. data/spec/lib/remote_resource/builder_spec.rb +1 -1
  33. data/spec/lib/remote_resource/collection_spec.rb +1 -1
  34. data/spec/lib/remote_resource/connection_options_spec.rb +20 -17
  35. data/spec/lib/remote_resource/connection_spec.rb +36 -27
  36. data/spec/lib/remote_resource/querying/finder_methods_spec.rb +199 -72
  37. data/spec/lib/remote_resource/querying/persistence_methods_spec.rb +228 -220
  38. data/spec/lib/remote_resource/request_spec.rb +313 -342
  39. data/spec/lib/remote_resource/response_spec.rb +9 -3
  40. data/spec/lib/remote_resource/rest_spec.rb +11 -11
  41. data/spec/lib/remote_resource/url_naming_determination_spec.rb +1 -1
  42. data/spec/lib/remote_resource/url_naming_spec.rb +7 -22
  43. data/spec/lib/remote_resource/util_spec.rb +56 -0
  44. data/spec/lib/remote_resource/version_spec.rb +2 -3
  45. data/spec/spec_helper.rb +37 -0
  46. metadata +33 -22
  47. data/lib/remote_resource/http_errors.rb +0 -33
  48. data/lib/remote_resource/response_handeling.rb +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae92e08ce0a95cfc8253c09f3106087caf9ba636
4
- data.tar.gz: 0e675db4069759cb3bf185c616821c78f55b1cad
3
+ metadata.gz: e3d2576b744b3dafd66aff8fca6d991f709fa10d
4
+ data.tar.gz: b32d6edb8af70dccdfe2b83cf4da340969b7f8b9
5
5
  SHA512:
6
- metadata.gz: 2b829236979e4f246503864b810da68b9939e84e2fdab2c288131a20bbde39fed70660b1a708d9390818e4d408579cf94db7508300c5cc1a3d1dc777cc84aeff
7
- data.tar.gz: d8ed2d8f09246377321acb6a2a0cd1a889e2090a2504509346d209f52cb6f541b3f7e30e890cbc72e06d778c36bd10c1071c74abf2adf909e48fb737b1f14796
6
+ metadata.gz: 3934a8a1d740a88e3cae6e8dc726c6af2bbb99bc35c4d8a25faf8ac6993fedcf5cdf67cf9093c9f6cf299b14eba9be50feb89a3527418720b0a8dc5f6e5f264f
7
+ data.tar.gz: 99b67f28cb4284c6100d69340e3f68020f4e13e3a5abedc99d62242858864b4846e9b207b6c1e79fc0834781e5e04a782cc6372bda5558aa06e29ee7a07d601e
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in remote_resource.gemspec
4
4
  gemspec
5
+
6
+ gem 'webmock', github: 'JanDintel/webmock', branch: ' feature/ignore-json-keys-order'
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
@@ -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 StandardError
24
+ RemoteResourceError = Class.new(StandardError)
26
25
 
27
26
  IdMissingError = Class.new(RemoteResourceError)
28
-
27
+
29
28
  CollectionOptionKeyError = Class.new(RemoteResourceError)
30
29
 
31
- RESTActionUnknown = Class.new RemoteResourceError # REST action
30
+ HTTPMethodUnsupported = Class.new(RemoteResourceError) # REST action
32
31
 
33
32
  class HTTPError < RemoteResourceError # HTTP errors
34
33
 
35
- def initialize(response)
36
- if response.try(:response_code)
37
- super "for url: #{response.try(:effective_url)} with HTTP response status: #{response.response_code} and response: #{response.inspect}"
38
- else
39
- super "for url: #{response.try(:effective_url)} with HTTP response: #{response.inspect}"
40
- end
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 HTTPError # HTTP 3xx
45
- HTTPClientError = Class.new HTTPError # HTTP 4xx
46
- HTTPServerError = Class.new HTTPError # HTTP 5xx
47
-
48
- HTTPBadRequest = Class.new HTTPClientError # HTTP 400
49
- HTTPUnauthorized = Class.new HTTPClientError # HTTP 401
50
- HTTPForbidden = Class.new HTTPClientError # HTTP 403
51
- HTTPNotFound = Class.new HTTPClientError # HTTP 404
52
- HTTPMethodNotAllowed = Class.new HTTPClientError # HTTP 405
53
- HTTPNotAcceptable = Class.new HTTPClientError # HTTP 406
54
- HTTPRequestTimeout = Class.new HTTPClientError # HTTP 408
55
- HTTPConflict = Class.new HTTPClientError # HTTP 409
56
- HTTPGone = Class.new HTTPClientError # HTTP 410
57
- HTTPTeapot = Class.new HTTPClientError # HTTP 418
58
-
59
- NginxClientError = Class.new HTTPClientError # HTTP errors used in Nginx
60
-
61
- HTTPNoResponse = Class.new NginxClientError # HTTP 444
62
- HTTPRequestHeaderTooLarge = Class.new NginxClientError # HTTP 494
63
- HTTPCertError = Class.new NginxClientError # HTTP 495
64
- HTTPNoCert = Class.new NginxClientError # HTTP 496
65
- HTTPToHTTPS = Class.new NginxClientError # HTTP 497
66
- HTTPClientClosedRequest = Class.new NginxClientError # HTTP 499
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
@@ -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
- id.present?
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? :each
116
+ return unless error_messages.respond_to?(:each)
109
117
 
110
118
  error_messages.each do |attribute, attribute_errors|
111
- attribute_errors.each do |error|
112
- self.errors.add attribute, error
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 :content_type, :default_headers, :extra_headers, instance_accessor: false
6
+ class_attribute :extension, :default_headers, instance_accessor: false
7
7
 
8
- self.content_type = '.json'
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
- self.default_headers.merge self.extra_headers || {}
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
- RemoteResource::Base::OPTIONS.each_with_object(Hash.new) do |option, hash|
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
- RemoteResource::Base::OPTIONS.each do |option|
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, { id: id }, connection_options.merge(no_attributes: true)).perform
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, connection_options).perform
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, params, connection_options.merge(collection: true)).perform
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, { id: id }, connection_options.reverse_merge(no_attributes: true)).perform
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, { id: id }, connection_options.reverse_merge(no_attributes: true)).perform
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
- attr_reader :resource, :rest_action, :attributes
4
+ SUPPORTED_HTTP_METHODS = [:get, :put, :patch, :post, :delete].freeze
6
5
 
7
- def initialize(resource, rest_action, attributes = {}, connection_options = {})
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
- @rest_action = rest_action.to_sym
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
- @connection_options.reverse_merge(threaded_connection_options).reverse_merge(resource.connection_options.to_hash)
21
- end
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
- def original_connection_options
24
- @original_connection_options.reverse_merge(threaded_connection_options)
37
+ default.deep_merge(block).deep_merge(local)
38
+ end
25
39
  end
26
40
 
27
41
  def perform
28
- case rest_action
29
- when :get
30
- response = connection.public_send rest_action, determined_request_url, params: determined_params, headers: determined_headers
31
- when :put, :patch, :post
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.response_code == 422
40
- RemoteResource::Response.new response, connection_options
47
+ if response.success? || response.unprocessable_entity?
48
+ response
41
49
  else
42
- raise_http_errors response
50
+ raise_http_error(self, response)
43
51
  end
44
52
  end
45
53
 
46
- def determined_request_url
47
- id = attributes[:id].presence
48
- base_url = original_connection_options[:base_url].presence || determined_url_naming.base_url(id, check_collection_options: true)
49
- content_type = connection_options[:content_type]
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
- "#{base_url}#{content_type}"
60
+ "#{base_url}#{extension}"
61
+ end
52
62
  end
53
63
 
54
- def determined_params
55
- no_params = connection_options[:no_params].eql? true
56
- no_attributes = connection_options[:no_attributes].eql? true
57
- params = connection_options[:params].presence || {}
64
+ def query
65
+ @query ||= begin
66
+ params = connection_options[:params]
58
67
 
59
- if no_params
60
- nil
61
- elsif no_attributes
62
- params
63
- else
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 determined_attributes
69
- no_attributes = connection_options[:no_attributes].eql? true
70
- root_element = connection_options[:root_element].presence
71
-
72
- if no_attributes
73
- {}
74
- elsif root_element
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 determined_headers
82
- headers = original_connection_options[:headers].presence || {}
86
+ def attributes
87
+ root_element = connection_options[:root_element]
83
88
 
84
- (connection_options[:default_headers].presence ||
85
- resource.connection_options.headers.merge(headers)).reverse_merge RemoteResource::Base.global_headers
89
+ if root_element.present?
90
+ { root_element => @attributes }
91
+ else
92
+ @attributes || {}
93
+ end
86
94
  end
87
95
 
88
- private
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
- def threaded_connection_options
91
- resource.try(:threaded_connection_options) || {}
102
+ default_headers.merge(global_headers).merge(headers).merge(conditional_headers)
103
+ end
92
104
  end
93
105
 
94
- def determined_url_naming
95
- RemoteResource::UrlNamingDetermination.new resource_klass, original_connection_options
106
+ def conditional_headers
107
+ headers = {}
108
+ headers = headers.merge(DEFAULT_CONTENT_TYPE) if body.present?
109
+ headers
96
110
  end
97
111
 
98
- def resource_klass
99
- resource.is_a?(Class) ? resource : resource.class
100
- end
112
+ private
101
113
 
102
- def pack_up_attributes(attributes, root_element)
103
- Hash[root_element.to_s, attributes]
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