ddy_remote_resource 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f35784393790ebf350ef35b54603bb614377dff0
4
- data.tar.gz: c76505446def63c7885faff3af1b0691405d2014
3
+ metadata.gz: 81d5006754f703089ef4ce8518c6d76d436f99e0
4
+ data.tar.gz: fe02833dc3ff9b27f2d737c22b0c7944600a39ad
5
5
  SHA512:
6
- metadata.gz: bb631e61a3730f260c44dec931ea1da7a97eda48c5dd4f4f56be1456a0d697183083c646cfe8c9210d827fd7bdd5c89594d9285ee28a1beb3f8740169c1b2f0f
7
- data.tar.gz: 609cc90d3de1c59bff32be7809df7eb24292d7806a0df1e35f9dbe38c2b7ab77d60608e41abacfd17f96260f17dc8d0e2f712668bbe21ed0ef3163d3e9df4ce1
6
+ metadata.gz: a7415dc3bc53bb4d491e0751bb27f231e066917f25069f4716480f6f307a0ee8111434770b166166aead5b1853dbdf7324f591ad1e27127896bf367080047a64
7
+ data.tar.gz: 2b66490233d2656431bd44afb72ef1de4d86bbecb0cbe4e11e5fc60cfff61317c2255dedbeb8d5b43ac2deb29250de96cdd5f357a45ce5c33967ee0c4aec5e6b
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RemoteResource
2
2
 
3
- RemoteResource is a gem to use resources with REST services.
3
+ RemoteResource is a gem to consume resources with REST services.
4
4
 
5
5
  ## Goal of RemoteResource
6
6
 
@@ -18,173 +18,184 @@ gem 'remote_resource', git: 'git@lab.digidentity.eu:jvanderpas/remote_resource.g
18
18
  gem 'ddy_remote_resource', require: 'remote_resource'
19
19
  ```
20
20
 
21
-
22
21
  ## Usage
23
22
 
24
23
  Simply include the `RemoteResource::Base` module in the class you want to enable for the REST services.
25
24
 
26
25
  ```ruby
27
- class ContactPerson
26
+ class Post
28
27
  include RemoteResource::Base
29
28
 
30
- self.site = "https://www.myapp.com"
31
- self.version = '/v2'
29
+ self.site = 'https://www.example.com'
30
+ self.collection = true # This option will become default in future versions
31
+
32
+ attribute :title, String
33
+ attribute :featured, Boolean
32
34
  end
33
35
  ```
34
36
 
35
- ### Options
36
-
37
- You can set a few options for the `RemoteResource` enabled class.
38
-
39
-
40
- #### Base URL options (`base_url`)
37
+ ### Querying
41
38
 
42
- The `base_url` is constructed from the `.site`, `.version`, `.path_prefix`, `.path_postfix`, `.collection`, `.collection_prefix`, and `.collection_name` options. The `.collection_name` is automatically constructed from the relative class name.
39
+ #### Finder methods
43
40
 
44
- We will use the `ContactPerson` class for these examples, with the `.collection_name` of `'contact_person'`:
41
+ To retrieve resources from the REST service, you can use the `.find`, `.find_by`, `.all` and `.where` class methods:
45
42
 
46
- * `.site`: This sets the URL which should be used to construct the `base_url`.
47
- * *Example:* `.site = "https://www.myapp.com"`
48
- * *`base_url`:* `https://www.myapp.com/contact_person`
49
- * `.version`: This sets the API version for the path, after the `.site` and before the `.path_prefix` that is used to construct the `base_url`.
50
- * *Example:* `.version = "/api/v2"`
51
- * *`base_url`:* `https://www.myapp.com/api/v2/contact_person`
52
- * `.path_prefix`: This sets the prefix for the path, after the `.version` and before the `.collection_name` that is used to construct the `base_url`.
53
- * *Example:* `.path_prefix = "/registration"`
54
- * *`base_url`:* `https://www.myapp.com/registration/contact_person`
55
- * `.path_postfix`: This sets the postfix for the path, after the `.collection_name` that is used to construct the `base_url`.
56
- * *Example:* `.path_postfix = "/new"`
57
- * *`base_url`:* `https://www.myapp.com/contact_person/new`
58
- * `.collection`: This toggles the pluralization of the `collection_name` that is used to construct the `base_url`.
59
- * *Default:* `false`
60
- * *Example:* `.collection = true`
61
- * *`base_url`:* `https://www.myapp.com/contact_persons`
62
- * `.collection_prefix`: This sets the prefix for the collection, before `collection_name` that is used to construct the `base_url`. The prefix variable has to be set via connection_options' key `collection_options`.
63
- * *Default:* ``
64
- * *Example:* `.collection_prefix = "/companies/:company_id"` and connection_options `collection_options: { company_id: 2 }`
65
- * *`base_url`:* `https://www.myapp.com/companies/2/contact_persons`
66
- * `.collection_name`: This sets the `collection_name` that is used to construct the `base_url`.
67
- * *Example:* `.collection_name = "company"`
68
- * *`base_url`:* `https://www.myapp.com/company`
43
+ ```ruby
44
+ # provide the `id` of the resource as argument
45
+ Post.find(12) #=> GET https://www.example.com/posts/12.json
69
46
 
70
- **override**
47
+ # provide the conditions as argument
48
+ Post.find_by(title: 'Our awesome post') #=> GET https://www.example.com/posts.json?title=Our+awesome+post
71
49
 
72
- To override the `base_url` completely, you can use the `base_url` option. This option should be passed into the `connection_options` hash when making a request:
50
+ # no arguments required
51
+ Post.all #=> GET https://www.example.com/posts.json
73
52
 
74
- * `base_url`: This sets the `base_url`. *note: this does not override the `.content_type` option*
75
- * *Example:* `{ base_url: "https://api.foo.com/v1" }`
76
- * *`base_url`:* `https://api.foo.com/v1`
53
+ # provide the conditions as argument
54
+ Post.where(ids: [10, 11, 12]) #=> GET https://www.example.com/posts.json?ids[]=10&ids[]=11&ids[]=12
55
+ ```
77
56
 
57
+ #### Persistence methods
78
58
 
79
- #### Request options
59
+ To create or alter resources from the REST service, you can use the `.create` and `.destroy` class methods or the `#save`, `#update_attributes` and `#destroy` instance methods:
80
60
 
81
- Apart from the options which manipulate the `base_url`, there are some more:
61
+ ```ruby
62
+ # provide the attributes as argument
63
+ Post.create(title: 'Our awesome post', featured: true) #=> POST https://www.example.com/posts.json
64
+
65
+ # provide the attributes on the resource
66
+ # new resource
67
+ post = Post.new
68
+ post.title = 'Our awesome post'
69
+ post.featured = true
70
+ post.save #=> POST https://www.example.com/posts.json
71
+
72
+ # existing resource
73
+ post = Post.new(id: 12)
74
+ post.title = 'Our awesome post'
75
+ post.featured = true
76
+ post.save #=> PATCH https://www.example.com/posts/12.json
77
+
78
+ # provide the attributes as argument
79
+ post = Post.new(id: 12, title: 'Our post')
80
+ post.update_attributes(title: 'Our awesome post', featured: true) #=> PATCH https://www.example.com/posts/12.json
81
+
82
+ # provide the `id` of the resource as argument
83
+ Post.destroy(12) #=> DELETE https://www.example.com/posts/12.json
84
+
85
+ # provide the `id` on the resource
86
+ post = Post.new(id: 12)
87
+ post.destroy #=> DELETE https://www.example.com/posts/12.json
88
+ ```
82
89
 
83
- * `.extra_headers`: This sets the extra headers which are merged with the `.default_headers` and should be used for the request. *note: you can't set the `.default_headers`*
84
- * *Default:* `.default_headers`: `{ "Content-Type" => "application/json" }`
85
- * *Example:* `.extra_headers = { "X-Locale" => "en" }`
86
- * `.headers`: `{ "Content-Type" => "application/json", "X-Locale" => "en" }`
87
- * `.content_type`: This sets the content-type which should be used for the request URL. *note: this is appended to the `base_url`*
88
- * *Default:* `".json"`
89
- * *`base_url`:* `https://www.myapp.com/contact_person`
90
- * *Example:* `.content-type = ".json"`
91
- * *Request URL:* `https://www.myapp.com/contact_person.json`
90
+ ### Connection options
91
+ You can provide some options to alter the request. The options can be given as the first or second argument when making a request.
92
92
 
93
- #### Body and params options
93
+ ```ruby
94
+ connection_options = { root_element: :data, headers: { "X-Locale" => "nl" } }
94
95
 
95
- Last but not least, you can pack the request body or params in a `root_element`:
96
+ Post.find(12, connection_options)
96
97
 
97
- * `.root_element`: This sets the `root_element` in which the request body or params should be 'packed' for the request.
98
- * *Params:* `{ email_address: "foo@bar.com", phone_number: "0031701234567" }`
99
- * *Example:* `.root_element = :contact_person`
100
- * *Packed params:* `{ "contact_person" => { email_address: "foo@bar.com", phone_number: "0031701234567" } }`
98
+ Post.all(connection_options)
101
99
 
100
+ Post.create({ title:'Our awesome post', featured: true }, connection_options)
102
101
 
103
- ### Querying
102
+ post = Post.new(id: 12)
103
+ post.title = 'Our awesome post'
104
+ post.featured = true
105
+ post.save(connection_options)
106
+ ```
104
107
 
105
- #### Finder methods
108
+ #### REST methods
106
109
 
107
- You can use the `.find`, `.find_by` and `.all` class methods:
110
+ You can make custom requests by using the REST methods directly. The following REST methods are defined: the `.get`, `.put`, `.patch` and `.post` class methods or the `#get`, `#put`, `#patch` and `#post` instance methods.
108
111
 
109
112
  ```ruby
110
- # use the `id` as argument
111
- ContactPerson.find(12)
113
+ Post.post(title: 'Our awesome post', featured: true) #=> RemoteResource::Response
114
+ ```
112
115
 
113
- # use a conditions `Hash` as argument
114
- ContactPerson.find_by(username: 'foobar')
116
+ ### Connection options
115
117
 
116
- # just the whole collection
117
- ContactPerson.all
118
- ```
118
+ You can provide some connection options to alter the request. The options can be defined on serveral ways:
119
+ - On the `RemoteResource` enabled class
120
+ - In the `.with_connection_options` block
121
+ - Directly as the first or second argument when making a request.
119
122
 
120
- To override the given `options`, you can pass in a `connection_options` hash:
121
123
 
122
- ```ruby
123
- connection_options: { root_element: :contact_person, headers: { "X-Locale" => "nl" } }
124
+ #### URL options
124
125
 
125
- # use the `id` as argument
126
- ContactPerson.find(12, connection_options)
126
+ There are several connection options that can alter the request URL. Normally the request URL is constructed using the `.site` and the relative class name of the `RemoteResource` enabled class. You can find this request URL by calling `.base_url` on the `RemoteResource` enabled class:
127
127
 
128
- # use a conditions `Hash` as argument
129
- ContactPerson.find_by((username: 'foobar'), connection_options)
128
+ ```ruby
129
+ Post.base_url #=> https://www.example.com/posts
130
130
  ```
131
131
 
132
- #### Persistence methods
132
+ We will use the `Post` class for these examples:
133
133
 
134
- You can use the `.create` class method and the `#save` instance method:
134
+ * `.site`: This sets the host which should be used to construct the `base_url`.
135
+ * *Example:* `.site = 'https://api.myapp.com'`
136
+ * `Post.base_url #=> https://api.myapp.com/posts`
137
+ * `.version`: This sets the API version for the path, after the `.site` and before the `.path_prefix` that is used to construct the `base_url`.
138
+ * *Example:* `.version = '/api/v2'`
139
+ * `Post.base_url #=> https://www.example.com/api/v2/posts`
140
+ * `.path_prefix`: This sets the prefix for the path, after the `.version` and before the `.collection_name` that is used to construct the `base_url`.
141
+ * *Example:* `.path_prefix = '/registration'`
142
+ * `Post.base_url #=> https://www.example.com/registration/posts`
143
+ * `.path_postfix`: This sets the postfix for the path, after the `.collection_name` that is used to construct the `base_url`.
144
+ * *Example:* `.path_postfix = '/new'`
145
+ * `Post.base_url #=> https://www.example.com/posts/new`
146
+ * `.collection`: This toggles the pluralization of the `collection_name` that is used to construct the `base_url`.
147
+ * *Default:* `false`, but will be `true` in future versions
148
+ * *Example:* `.collection = false`
149
+ * `Post.base_url #=> https://www.example.com/post`
150
+ * `.collection_prefix`: This sets the prefix for the collection, before `collection_name` that is used to construct the `base_url`. The prefix variable has to be set via connection_options' key `collection_options`.
151
+ * *Example:* `.collection_prefix = '/companies/:company_id'`
152
+ * `Post.base_url #=> https://www.example.com/companies/:company_id/posts`
153
+ * `Post.base_url(collection_options: { company_id: 2 }) #=> https://www.example.com/companies/2/posts`
154
+ * `.collection_name`: This sets the `collection_name` that is used to construct the `base_url`.
155
+ * *Example:* `.collection_name = 'company'`
156
+ * `Post.base_url #=> https://www.example.com/company`
135
157
 
136
158
 
137
- ```ruby
138
- # .create
139
- ContactPerson.create(username: 'aapmies', first_name: 'Mies')
159
+ #### Request options
140
160
 
141
- # #save
142
- contact_person = ContactPerson.new(id: 12)
143
- contact_person.username = 'aapmies'
144
- contact_person.save
145
- ```
146
- To override the given `options`, you can pass in a `connection_options` hash:
161
+ Apart from the options which manipulate the request URL, there are also options to alter the request:
147
162
 
148
- ```ruby
149
- connection_options: { root_element: :contact_person, headers: { "X-Locale" => "nl" } }
163
+ * `.default_headers`: This sets the default headers.
164
+ * *Default:* `{ "Accept" => "application/json", "User-Agent" => "RemoteResource <version>" }`
165
+ * *Example:* `.headers = { "User-Agent" => "My App" }`
166
+ * `{ "User-Agent" => "My App" }`
167
+ * `.headers`: This sets the headers which are merged with the default headers.
168
+ * *Default:* `{ "Accept" => "application/json", "User-Agent" => "RemoteResource <version>" }`
169
+ * *Example:* `.headers = { "X-Locale" => "en" }`
170
+ * `{ "Accept" => "application/json", "User-Agent" => "RemoteResource <version>", "X-Locale" => "en" }`
150
171
 
151
- contact_person = ContactPerson.new(id: 12)
152
- contact_person.username = 'aapmies'
153
- contact_person.save(connection_options)
154
- ```
155
172
 
156
- #### REST methods
173
+ #### Body options
157
174
 
158
- You can use the `.get`, `.put`, `.patch` and `.post` class methods and the `
159
- #get`, `#put`, `#patch` and `#post` instance methods.
175
+ Some API wrap the resource within a specific element, we call this element the root element. When a root element is given as option the attributes in the request body will be wrapped in the element and the attributes of the response will be unwrapped from the element.
160
176
 
177
+ * `.root_element`: This sets the element in which the body is wrapped.
178
+ * *Example:* `.root_element = :data`
179
+ * `{"data":{"title":"My awesome post", "featured":true}}`
161
180
 
162
- #### With a `connection_options` block
181
+ #### Using the `.with_connection_options` block
163
182
 
164
- You can make your requests in a `connection_options` block. All the requests in the block will use the passed in `connection_options`.
183
+ You can make your requests in a `.with_connection_options` block. All the requests in the block will use the passed in connection options.
165
184
 
166
185
  ```ruby
167
- ContactPerson.with_connection_options(headers: { "X-Locale" => "en" }) do
168
- ContactPerson.find_by(username: 'foobar')
169
- ContactPerson.find_by(username: 'aapmies', (content-type: '.xml'))
170
- ContactPerson.find_by((username: 'viking'), (headers: { "X-Locale" => "nl" }))
186
+ Post.with_connection_options(headers: { "X-Locale" => "en" }) do
187
+ Post.find(12)
188
+ Post.where({ featured: true }, { version: '/api/v2' })
189
+ Post.all({ collection_prefix: '/companies/:company_id', collection_options: { company_id: 10 })
171
190
  end
172
191
  ```
173
192
 
174
- This will result in two request which use the `{ headers: { "X-Locale" => "en" } }` as `connection_options`, one which will use the `{ headers: { "X-Locale" => "nl" } }` as `connection_options`. And one that will append `.xml` to the request URL.
175
-
176
- ### Responses
177
-
178
- The response body of the request will be 'unpacked' from the `root_element` if necessary and parsed. The resulting `Hash` will be used to assign the attributes of the resource.
179
-
180
- However if you want to access the response of the request, you can use the `#_response` method. This returns a `RemoteResource::Response` object with the `#response_body` and `#response_code` methods.
193
+ ### Debug methods
181
194
 
195
+ The last request and response of the resource is set on the resource. You can use this to debug your implementation.
182
196
 
183
197
  ```ruby
184
- contact_person = ContactPerson.find_by((username: 'foobar'), connection_options)
185
- contact_person._response #=> RemoteResource::Response
186
- contact_person._response.response_code #=> 200
187
- contact_person._response.response_body #=> '{"username":"foobar", "name":"Foo", "surname":"Bar"}'
198
+ post = Post.find(12)
199
+ post.last_request #=> RemoteResource::Request
200
+ post.last_response #=> RemoteResource::Response
188
201
  ```
189
-
190
-
@@ -19,11 +19,12 @@ module RemoteResource
19
19
  include RemoteResource::Querying::FinderMethods
20
20
  include RemoteResource::Querying::PersistenceMethods
21
21
 
22
- attr_accessor :_response
22
+ attr_accessor :last_request, :last_response, :meta
23
23
  attr_accessor :destroyed
24
24
 
25
- attribute :id
26
25
  class_attribute :root_element, instance_accessor: false
26
+
27
+ attribute :id
27
28
  end
28
29
 
29
30
  def self.global_headers=(headers)
@@ -85,7 +86,7 @@ module RemoteResource
85
86
  end
86
87
 
87
88
  def success?
88
- _response.success? && !errors?
89
+ last_response.success? && !errors?
89
90
  end
90
91
 
91
92
  def errors?
@@ -94,20 +95,19 @@ module RemoteResource
94
95
 
95
96
  def handle_response(response)
96
97
  if response.unprocessable_entity?
97
- rebuild_resource_from_response(response).tap do |resource|
98
- resource.assign_errors_from_response response
99
- end
98
+ rebuild_resource_from_response(response)
99
+ assign_errors_from_response(response)
100
100
  else
101
101
  rebuild_resource_from_response(response)
102
- end
102
+ end and self
103
103
  end
104
104
 
105
- def assign_response(response)
106
- @_response = response
105
+ def assign_errors_from_response(response)
106
+ assign_errors(response.errors)
107
107
  end
108
108
 
109
- def assign_errors_from_response(response)
110
- assign_errors response.error_messages_response_body
109
+ def _response
110
+ warn '[DEPRECATION] `._response` is deprecated. Please use `.last_response` instead.'
111
111
  end
112
112
 
113
113
  private
@@ -5,49 +5,37 @@ module RemoteResource
5
5
  module ClassMethods
6
6
 
7
7
  def build_resource_from_response(response)
8
- build_resource response.sanitized_response_body, response_hash(response)
8
+ build_resource(response.attributes, { last_request: response.request, last_response: response, meta: response.meta })
9
9
  end
10
10
 
11
- def build_resource(collection, response_hash = {})
12
- if collection.is_a? Hash
13
- new collection.merge response_hash
11
+ def build_resource(collection, options = {})
12
+ if collection.is_a?(Hash)
13
+ new(collection.merge(options))
14
14
  end
15
15
  end
16
16
 
17
17
  def build_collection_from_response(response)
18
- build_collection response.sanitized_response_body, response_hash(response)
18
+ build_collection(response.attributes, { last_request: response.request, last_response: response, meta: response.meta })
19
19
  end
20
20
 
21
- def build_collection(collection, response_hash = {})
22
- if collection.is_a? Array
23
- RemoteResource::Collection.new self, collection, response_hash
21
+ def build_collection(collection, options = {})
22
+ if collection.is_a?(Array)
23
+ RemoteResource::Collection.new(self, collection, options)
24
24
  end
25
25
  end
26
-
27
- private
28
-
29
- def response_hash(response_object)
30
- { _response: response_object, meta: response_object.sanitized_response_meta }
31
- end
32
26
  end
33
27
 
34
28
  def rebuild_resource_from_response(response)
35
- rebuild_resource response.sanitized_response_body, response_hash(response)
29
+ rebuild_resource(response.attributes, { last_request: response.request, last_response: response, meta: response.meta })
36
30
  end
37
31
 
38
- def rebuild_resource(collection, response_hash = {})
39
- if collection.is_a? Hash
40
- self.attributes = collection.merge(response_hash)
32
+ def rebuild_resource(collection, options = {})
33
+ if collection.is_a?(Hash)
34
+ self.attributes = collection.merge(options)
41
35
  else
42
- self.attributes = response_hash
36
+ self.attributes = options
43
37
  end and self
44
38
  end
45
39
 
46
- private
47
-
48
- def response_hash(response_object)
49
- self.class.send :response_hash, response_object
50
- end
51
-
52
40
  end
53
41
  end
@@ -2,27 +2,26 @@ module RemoteResource
2
2
  class Collection
3
3
  include Enumerable
4
4
 
5
- delegate :[], :at, :reverse, :size, to: :to_a
5
+ attr_reader :resource_klass, :resources_collection
6
+ attr_accessor :last_request, :last_response, :meta
6
7
 
7
- attr_reader :resource_klass, :resources_collection, :meta, :_response
8
+ delegate :[], :at, :reverse, :size, to: :to_a
8
9
 
9
- def initialize(resource_klass, resources_collection, response_hash)
10
+ def initialize(resource_klass, resources_collection, options = {})
10
11
  @resource_klass = resource_klass
11
12
  @resources_collection = resources_collection
12
- @response_hash = response_hash
13
- @meta = response_hash[:meta] || {}
14
- @_response = response_hash[:_response]
13
+ @options = options
15
14
  end
16
15
 
17
16
  def each(&block)
18
- if resources_collection.is_a? Array
17
+ if resources_collection.is_a?(Array)
19
18
  if defined?(@collection)
20
19
  @collection.each(&block)
21
20
  else
22
21
  @collection = []
23
22
  resources_collection.each do |element|
24
- record = resource_klass.new element.merge(@response_hash)
25
- @collection << record
23
+ record = resource_klass.new(element.merge(@options))
24
+ @collection.push(record)
26
25
  yield(record)
27
26
  end
28
27
  end
@@ -34,7 +33,23 @@ module RemoteResource
34
33
  end
35
34
 
36
35
  def success?
37
- _response.success?
36
+ last_response.success?
37
+ end
38
+
39
+ def last_request
40
+ @last_request ||= @options[:last_request]
41
+ end
42
+
43
+ def last_response
44
+ @last_response ||= @options[:last_response]
45
+ end
46
+
47
+ def meta
48
+ @meta ||= @options[:meta]
49
+ end
50
+
51
+ def _response
52
+ warn '[DEPRECATION] `._response` is deprecated. Please use `.last_response` instead.'
38
53
  end
39
54
 
40
55
  end
@@ -42,7 +42,7 @@ module RemoteResource
42
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
43
 
44
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)
45
+ response = RemoteResource::Response.new(connection_response, connection_options.merge(request: self, connection_request: connection_response.request))
46
46
 
47
47
  if response.success? || response.unprocessable_entity?
48
48
  response
@@ -1,81 +1,63 @@
1
1
  module RemoteResource
2
2
  class Response
3
3
 
4
- attr_reader :original_response, :original_request
5
- private :original_response, :original_request
4
+ def initialize(connection_response, connection_options = {})
5
+ @connection_response = connection_response
6
+ @connection_request = connection_options[:connection_request]
7
+ @request = connection_options[:request]
8
+ @connection_options = connection_options
9
+ end
6
10
 
7
- def initialize(response, connection_options = {})
8
- @original_response = response
9
- @original_request = response.request
10
- @connection_options = connection_options
11
+ def request
12
+ @request
11
13
  end
12
14
 
13
15
  def success?
14
- original_response.success?
16
+ @connection_response.success?
15
17
  end
16
18
 
17
19
  def unprocessable_entity?
18
20
  response_code == 422
19
21
  end
20
22
 
21
- def response_body
22
- original_response.body
23
- end
24
-
25
23
  def response_code
26
- original_response.response_code
24
+ @response_code ||= @connection_response.response_code
27
25
  end
28
26
 
29
- def response_headers
30
- original_response.headers
27
+ def headers
28
+ @headers ||= @connection_response.headers
31
29
  end
32
30
 
33
- def sanitized_response_body
34
- return empty_hash if response_body.blank?
35
- return empty_hash if parsed_response_body.blank?
36
-
37
- unpacked_parsed_response_body
31
+ def body
32
+ @body ||= @connection_response.body
38
33
  end
39
34
 
40
- def sanitized_response_meta
41
- return empty_hash if response_body.blank?
42
- return empty_hash if parsed_response_body.blank?
43
-
44
- return parsed_response_body['meta'] if parsed_response_body.try :has_key?, 'meta'
45
-
46
- empty_hash
35
+ def parsed_body
36
+ @parsed_body ||= begin
37
+ JSON.parse(body.to_s)
38
+ rescue JSON::ParserError
39
+ {}
40
+ end
47
41
  end
48
42
 
49
- def error_messages_response_body
50
- return empty_hash if response_body.blank?
51
- return empty_hash if parsed_response_body.blank?
43
+ def attributes
44
+ @attributes ||= begin
45
+ root_element = @connection_options[:root_element]
52
46
 
53
- return parsed_response_body["errors"] if parsed_response_body.try :has_key?, "errors"
54
- return unpacked_parsed_response_body["errors"] if unpacked_parsed_response_body.try :has_key?, "errors"
55
-
56
- empty_hash
47
+ if root_element.present?
48
+ parsed_body[root_element.to_s]
49
+ else
50
+ parsed_body
51
+ end.presence || {}
52
+ end
57
53
  end
58
54
 
59
- def parsed_response_body
60
- @parsed_response_body ||= JSON.parse response_body
61
- rescue JSON::ParserError
62
- nil
55
+ def errors
56
+ @errors ||= parsed_body['errors'].presence || attributes['errors'].presence || {}
63
57
  end
64
58
 
65
- private
66
-
67
- def empty_hash
68
- {}
69
- end
70
-
71
- def unpacked_parsed_response_body
72
- root_element = @connection_options[:root_element].presence
73
-
74
- if root_element
75
- parsed_response_body[root_element.to_s]
76
- else
77
- parsed_response_body
78
- end
59
+ def meta
60
+ @meta ||= parsed_body['meta'].presence || {}
79
61
  end
80
62
 
81
63
  end
@@ -1,3 +1,3 @@
1
1
  module RemoteResource
2
- VERSION = '1.0.0.rc2'.freeze
2
+ VERSION = '1.0.0.rc3'.freeze
3
3
  end