ddy_remote_resource 1.0.0.rc2 → 1.0.0.rc3
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/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
|