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 +4 -4
- data/README.md +125 -114
- data/lib/remote_resource/base.rb +11 -11
- data/lib/remote_resource/builder.rb +13 -25
- data/lib/remote_resource/collection.rb +25 -10
- data/lib/remote_resource/request.rb +1 -1
- data/lib/remote_resource/response.rb +33 -51
- data/lib/remote_resource/version.rb +1 -1
- data/spec/lib/remote_resource/base_spec.rb +62 -50
- data/spec/lib/remote_resource/builder_spec.rb +169 -173
- data/spec/lib/remote_resource/collection_spec.rb +94 -27
- data/spec/lib/remote_resource/request_spec.rb +14 -4
- data/spec/lib/remote_resource/response_spec.rb +102 -169
- data/spec/lib/remote_resource/version_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81d5006754f703089ef4ce8518c6d76d436f99e0
|
4
|
+
data.tar.gz: fe02833dc3ff9b27f2d737c22b0c7944600a39ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
26
|
+
class Post
|
28
27
|
include RemoteResource::Base
|
29
28
|
|
30
|
-
self.site
|
31
|
-
self.
|
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
|
-
###
|
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
|
-
|
39
|
+
#### Finder methods
|
43
40
|
|
44
|
-
|
41
|
+
To retrieve resources from the REST service, you can use the `.find`, `.find_by`, `.all` and `.where` class methods:
|
45
42
|
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
50
|
+
# no arguments required
|
51
|
+
Post.all #=> GET https://www.example.com/posts.json
|
73
52
|
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
84
|
-
|
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
|
-
|
93
|
+
```ruby
|
94
|
+
connection_options = { root_element: :data, headers: { "X-Locale" => "nl" } }
|
94
95
|
|
95
|
-
|
96
|
+
Post.find(12, connection_options)
|
96
97
|
|
97
|
-
|
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
|
-
|
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
|
-
####
|
108
|
+
#### REST methods
|
106
109
|
|
107
|
-
You can
|
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
|
-
|
111
|
-
|
113
|
+
Post.post(title: 'Our awesome post', featured: true) #=> RemoteResource::Response
|
114
|
+
```
|
112
115
|
|
113
|
-
|
114
|
-
ContactPerson.find_by(username: 'foobar')
|
116
|
+
### Connection options
|
115
117
|
|
116
|
-
|
117
|
-
|
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
|
-
|
123
|
-
connection_options: { root_element: :contact_person, headers: { "X-Locale" => "nl" } }
|
124
|
+
#### URL options
|
124
125
|
|
125
|
-
|
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
|
-
|
129
|
-
|
128
|
+
```ruby
|
129
|
+
Post.base_url #=> https://www.example.com/posts
|
130
130
|
```
|
131
131
|
|
132
|
-
|
132
|
+
We will use the `Post` class for these examples:
|
133
133
|
|
134
|
-
|
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
|
-
|
138
|
-
# .create
|
139
|
-
ContactPerson.create(username: 'aapmies', first_name: 'Mies')
|
159
|
+
#### Request options
|
140
160
|
|
141
|
-
|
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
|
-
|
149
|
-
|
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
|
-
####
|
173
|
+
#### Body options
|
157
174
|
|
158
|
-
|
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
|
-
####
|
181
|
+
#### Using the `.with_connection_options` block
|
163
182
|
|
164
|
-
You can make your requests in a `
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
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
|
-
|
data/lib/remote_resource/base.rb
CHANGED
@@ -19,11 +19,12 @@ module RemoteResource
|
|
19
19
|
include RemoteResource::Querying::FinderMethods
|
20
20
|
include RemoteResource::Querying::PersistenceMethods
|
21
21
|
|
22
|
-
attr_accessor :
|
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
|
-
|
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)
|
98
|
-
|
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
|
106
|
-
|
105
|
+
def assign_errors_from_response(response)
|
106
|
+
assign_errors(response.errors)
|
107
107
|
end
|
108
108
|
|
109
|
-
def
|
110
|
-
|
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.
|
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,
|
12
|
-
if collection.is_a?
|
13
|
-
new
|
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.
|
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,
|
22
|
-
if collection.is_a?
|
23
|
-
RemoteResource::Collection.new
|
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.
|
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,
|
39
|
-
if collection.is_a?
|
40
|
-
self.attributes = collection.merge(
|
32
|
+
def rebuild_resource(collection, options = {})
|
33
|
+
if collection.is_a?(Hash)
|
34
|
+
self.attributes = collection.merge(options)
|
41
35
|
else
|
42
|
-
self.attributes =
|
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
|
-
|
5
|
+
attr_reader :resource_klass, :resources_collection
|
6
|
+
attr_accessor :last_request, :last_response, :meta
|
6
7
|
|
7
|
-
|
8
|
+
delegate :[], :at, :reverse, :size, to: :to_a
|
8
9
|
|
9
|
-
def initialize(resource_klass, resources_collection,
|
10
|
+
def initialize(resource_klass, resources_collection, options = {})
|
10
11
|
@resource_klass = resource_klass
|
11
12
|
@resources_collection = resources_collection
|
12
|
-
@
|
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?
|
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
|
25
|
-
@collection
|
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
|
-
|
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
|
-
|
5
|
-
|
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
|
8
|
-
@
|
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
|
-
|
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
|
-
|
24
|
+
@response_code ||= @connection_response.response_code
|
27
25
|
end
|
28
26
|
|
29
|
-
def
|
30
|
-
|
27
|
+
def headers
|
28
|
+
@headers ||= @connection_response.headers
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
|
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
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
50
|
-
|
51
|
-
|
43
|
+
def attributes
|
44
|
+
@attributes ||= begin
|
45
|
+
root_element = @connection_options[:root_element]
|
52
46
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
60
|
-
@
|
61
|
-
rescue JSON::ParserError
|
62
|
-
nil
|
55
|
+
def errors
|
56
|
+
@errors ||= parsed_body['errors'].presence || attributes['errors'].presence || {}
|
63
57
|
end
|
64
58
|
|
65
|
-
|
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
|