api-resource 0.5.5 → 0.6.0
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/lib/api-resource/resource.rb +73 -44
- data/lib/api-resource/version.rb +1 -1
- data/spec/resource_spec.rb +44 -20
- 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: e3dab8e5d2531d7f27d4034f61818e59037d4b23
|
4
|
+
data.tar.gz: b2a85b96d4c0a9bcfdacef705f89bf6c355b626f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8c31ce73a48fbb84b298bf85e1748e428b89a2b668ebc0a0a736c764d25eba665f3b91674146bb1c5b76c93b5087c8d1e55fcfcd464f56565df507b523d5701
|
7
|
+
data.tar.gz: 559e1cae1d406f0fee084820137e6ea5ff74a18eaf889fafcb11bb54e23bc5d60afe024bf2df89fc89fac3a0f14fa711b74b50a271eeff645b9f60259b30e2f3
|
@@ -22,8 +22,12 @@ module ApiResource
|
|
22
22
|
class_attribute :api_id
|
23
23
|
class_attribute :api_secret
|
24
24
|
class_attribute :hmac_options
|
25
|
-
class_attribute :
|
26
|
-
class_attribute :
|
25
|
+
class_attribute :pre_submit_filter
|
26
|
+
class_attribute :default_id_attr
|
27
|
+
self.default_id_attr = :id
|
28
|
+
class_attribute :default_per_page
|
29
|
+
self.default_per_page = 500
|
30
|
+
class_attribute :logger
|
27
31
|
|
28
32
|
def self.with_hmac(api_id, api_secret, options={})
|
29
33
|
self.hmac = true
|
@@ -33,7 +37,7 @@ module ApiResource
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def self.filter_submitted_attributes(&block)
|
36
|
-
self.
|
40
|
+
self.pre_submit_filter = block if block_given?
|
37
41
|
end
|
38
42
|
|
39
43
|
def initialize(hash=nil)
|
@@ -52,18 +56,22 @@ module ApiResource
|
|
52
56
|
self.class.resource_path
|
53
57
|
end
|
54
58
|
|
59
|
+
def resource_path=(path)
|
60
|
+
self.class.resource_path = path
|
61
|
+
end
|
62
|
+
|
55
63
|
def self.find(id)
|
56
64
|
result = client(:get, {}, resource_path, id)
|
57
65
|
json = JSON.parse(result)
|
58
66
|
self.new(json['data'] || json)
|
59
67
|
end
|
60
68
|
|
61
|
-
def self.all
|
62
|
-
self.where({},
|
69
|
+
def self.all(method=:get)
|
70
|
+
self.where({}, method)
|
63
71
|
end
|
64
72
|
|
65
73
|
def self.all_pages(options={})
|
66
|
-
options = { page: 1, per_page:
|
74
|
+
options = { page: 1, per_page: default_per_page }.merge(options)
|
67
75
|
per_page = options[:per_page].to_i
|
68
76
|
page = options[:page].to_i
|
69
77
|
begin
|
@@ -77,20 +85,20 @@ module ApiResource
|
|
77
85
|
end while true
|
78
86
|
end
|
79
87
|
|
80
|
-
def self.where(options,
|
81
|
-
result = client(
|
88
|
+
def self.where(options, method=:get)
|
89
|
+
result = client(method, options, resource_path)
|
82
90
|
create_resource_collection(result)
|
83
91
|
end
|
84
92
|
|
85
|
-
def save!
|
86
|
-
submit_resource(resource_path, true)
|
93
|
+
def save!(options={})
|
94
|
+
submit_resource(resource_path, true, options[:id_attr])
|
87
95
|
self
|
88
96
|
end
|
89
97
|
|
90
98
|
def submit!(options={})
|
91
99
|
path = options.fetch(:path, resource_path)
|
92
100
|
type = options[:type]
|
93
|
-
json = submit_resource(path, false)
|
101
|
+
json = submit_resource(path, false, options[:id_attr])
|
94
102
|
meta = json && json['meta']
|
95
103
|
type ||= meta && meta['type']
|
96
104
|
if type
|
@@ -101,8 +109,8 @@ module ApiResource
|
|
101
109
|
end
|
102
110
|
end
|
103
111
|
|
104
|
-
def destroy!
|
105
|
-
self.
|
112
|
+
def destroy!(options={})
|
113
|
+
self.submit_resource(resource_path, false, options[:id_attr], :delete)
|
106
114
|
self
|
107
115
|
end
|
108
116
|
|
@@ -112,23 +120,6 @@ module ApiResource
|
|
112
120
|
|
113
121
|
protected
|
114
122
|
|
115
|
-
def submit_resource(path, save_attributes=false)
|
116
|
-
raise ResourceError unless valid?
|
117
|
-
verb = respond_to?(:id) && id ? :put : :post
|
118
|
-
begin
|
119
|
-
attrs = attributes
|
120
|
-
attrs = submitted_attributes_filter[attrs] if submitted_attributes_filter
|
121
|
-
result = self.class.client(verb, attrs, path)
|
122
|
-
rescue RestClient::ExceptionWithResponse => e
|
123
|
-
result = e.http_body
|
124
|
-
raise ResourceError, 'Error executing request'
|
125
|
-
ensure
|
126
|
-
json = parse_and_check_error(result)
|
127
|
-
self.attributes = json['data'] || json if json && verb == :post && save_attributes
|
128
|
-
end
|
129
|
-
json
|
130
|
-
end
|
131
|
-
|
132
123
|
def parse_and_check_error(result)
|
133
124
|
return nil if result.blank?
|
134
125
|
json = JSON.parse(result)
|
@@ -171,20 +162,31 @@ module ApiResource
|
|
171
162
|
def self.method_missing(m, *args, &_)
|
172
163
|
case (m)
|
173
164
|
when /^by_(.+)/
|
174
|
-
|
165
|
+
resource_path = self.resource_path
|
166
|
+
Class.new(self) do
|
167
|
+
self.resource_path = build_url($1.pluralize, args[0], resource_path)
|
168
|
+
end
|
175
169
|
else
|
176
170
|
super
|
177
171
|
end
|
178
172
|
end
|
179
173
|
|
180
|
-
def
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
174
|
+
def method_missing(m, *args, &_)
|
175
|
+
case m
|
176
|
+
when /^by_(.+)/
|
177
|
+
begin
|
178
|
+
original_path = resource_path
|
179
|
+
self.resource_path = self.class.build_url($1, args[0], resource_path)
|
180
|
+
yield(self) if block_given?
|
181
|
+
ensure
|
182
|
+
self.resource_path = original_path
|
183
|
+
end
|
184
|
+
else
|
185
|
+
super
|
185
186
|
end
|
186
187
|
end
|
187
188
|
|
189
|
+
|
188
190
|
def self.create_resource_collection(result)
|
189
191
|
json = JSON.parse(result)
|
190
192
|
ResourceCollection.new(json['data'], json['meta'], self)
|
@@ -196,11 +198,37 @@ module ApiResource
|
|
196
198
|
klass if klass && klass < ApiResource::Resource
|
197
199
|
end
|
198
200
|
|
199
|
-
def
|
201
|
+
def submit_resource(path, save_attrs=false, id_attr=nil, method=nil)
|
202
|
+
raise ResourceError unless valid?
|
203
|
+
id_attr = id_attr || default_id_attr
|
204
|
+
path = [path]
|
205
|
+
attrs = attributes
|
206
|
+
id_value = attrs[id_attr]
|
207
|
+
method = method || (id_value.nil? ? :post : :put)
|
208
|
+
|
209
|
+
if method != :post && id_value
|
210
|
+
path << id_value
|
211
|
+
attrs.delete(id_attr)
|
212
|
+
end
|
213
|
+
attrs = {} if method == :delete
|
214
|
+
attrs = pre_submit_filter[attrs] if pre_submit_filter
|
215
|
+
begin
|
216
|
+
result = self.class.client(method, attrs, *path)
|
217
|
+
rescue RestClient::ExceptionWithResponse => e
|
218
|
+
result = e.http_body
|
219
|
+
raise ResourceError, 'Error executing request'
|
220
|
+
ensure
|
221
|
+
json = parse_and_check_error(result)
|
222
|
+
self.attributes = json['data'] || json if json && method == :post && save_attrs
|
223
|
+
end
|
224
|
+
json
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.client(method, params, *paths)
|
200
228
|
url = build_url(*paths)
|
201
229
|
headers = { accept: :json }
|
202
|
-
req_params = { url: url, method:
|
203
|
-
if
|
230
|
+
req_params = { url: url, method: method, headers: headers }
|
231
|
+
if method == :get
|
204
232
|
# using #to_query instead of URI::encode_www_form to comply with rails convention for query string array values
|
205
233
|
req_params[:url] = "#{url}?#{params.to_query}" unless params.to_query.blank?
|
206
234
|
else
|
@@ -211,7 +239,7 @@ module ApiResource
|
|
211
239
|
req.sign!(api_id, api_secret, hmac_options)
|
212
240
|
end
|
213
241
|
result = req.execute
|
214
|
-
|
242
|
+
log << result
|
215
243
|
result
|
216
244
|
end
|
217
245
|
|
@@ -220,12 +248,12 @@ module ApiResource
|
|
220
248
|
URI::parse(base_url).merge(paths.map { |p| "#{URI.encode p.to_s}" }.join('/')).to_s
|
221
249
|
end
|
222
250
|
|
223
|
-
def self.
|
224
|
-
self.
|
251
|
+
def self.log=(param)
|
252
|
+
self.logger = create_log(param)
|
225
253
|
end
|
226
254
|
|
227
|
-
def self.
|
228
|
-
self.
|
255
|
+
def self.log
|
256
|
+
self.logger ||= Class.new do
|
229
257
|
def <<(_)
|
230
258
|
end
|
231
259
|
end.new
|
@@ -261,6 +289,7 @@ module ApiResource
|
|
261
289
|
end
|
262
290
|
end
|
263
291
|
end
|
292
|
+
|
264
293
|
class ResourceCollection
|
265
294
|
include Enumerable
|
266
295
|
|
data/lib/api-resource/version.rb
CHANGED
data/spec/resource_spec.rb
CHANGED
@@ -10,6 +10,7 @@ RSpec.describe ApiResource::Resource do
|
|
10
10
|
|
11
11
|
class Blog < Resource
|
12
12
|
attr_accessor :id, :title
|
13
|
+
|
13
14
|
def do_stuff_method
|
14
15
|
end
|
15
16
|
end
|
@@ -46,7 +47,7 @@ RSpec.describe ApiResource::Resource do
|
|
46
47
|
it 'retrieves all pages' do
|
47
48
|
expected_values = (1..223).map { |i| { id: i, title: "Hello #{i}" } }.each_slice(100).to_a
|
48
49
|
expected_values.each_with_index do |objs, i|
|
49
|
-
req(:get, "/blogs?page=#{i+1}&per_page=100", { data: objs, meta: { total_count: 223 } })
|
50
|
+
req(:get, "/blogs?page=#{ i+1 }&per_page=100", { data: objs, meta: { total_count: 223 } })
|
50
51
|
end
|
51
52
|
|
52
53
|
i = 1
|
@@ -73,6 +74,7 @@ RSpec.describe ApiResource::Resource do
|
|
73
74
|
it 'creates resource with data rooted json' do
|
74
75
|
check_found_resource(data: { id: 1257, title: 'Hello' })
|
75
76
|
end
|
77
|
+
|
76
78
|
it 'creates resource with un-rooted json' do
|
77
79
|
check_found_resource(id: 1257, title: 'Hello')
|
78
80
|
end
|
@@ -202,44 +204,66 @@ RSpec.describe ApiResource::Resource do
|
|
202
204
|
end
|
203
205
|
|
204
206
|
context '#save!' do
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
expected_value = { data: { id: 32, title: 'hello' } }
|
207
|
+
let(:blog_attrs) { { id: 525, title: 'hello' } }
|
208
|
+
let(:blog_id) { blog_attrs[:id] }
|
209
|
+
let(:expected_value) { { data: blog_attrs } }
|
209
210
|
|
210
|
-
|
211
|
+
it 'POSTs data when id is nil' do
|
212
|
+
blog = BlogApi::Blog.new(title: 'hello')
|
213
|
+
stub = req(:post, '/blogs', expected_value, 201, blog_attrs.except(:id))
|
211
214
|
returned = blog.save!
|
212
|
-
expect(returned).to eq(blog)
|
213
215
|
check_returned_object(BlogApi::Blog, expected_value, blog)
|
216
|
+
expect(returned).to eq(blog)
|
217
|
+
expect(blog.id).to eq(blog_id)
|
214
218
|
expect(stub).to have_been_requested
|
215
219
|
end
|
216
|
-
it 'PUTs data when id is not nil' do
|
217
|
-
blog_id = 525
|
218
|
-
blog = BlogApi::Blog.new(id: blog_id, title: 'hello')
|
219
220
|
|
220
|
-
|
221
|
+
it 'PUTs data when id is not nil' do
|
222
|
+
blog = BlogApi::Blog.new(id: blog_id, title: 'hello')
|
223
|
+
stub = req(:put, "/blogs/#{blog_id}", nil, 204, blog_attrs.except(:id))
|
221
224
|
returned = blog.save!
|
222
225
|
expect(returned).to eq(blog)
|
223
226
|
expect(blog.id).to eq(blog_id)
|
224
227
|
expect(stub).to have_been_requested
|
225
228
|
end
|
229
|
+
|
230
|
+
context '#by_resource' do
|
231
|
+
it 'POSTs data in parent resource context' do
|
232
|
+
blog_id = 525
|
233
|
+
blog = BlogApi::Blog.new(title: 'hello')
|
234
|
+
expected_value = { data: { id: blog_id, title: 'hello' } }
|
235
|
+
user_id = 'ux345'
|
236
|
+
|
237
|
+
stub = req(:post, "/users/#{user_id}/blogs", expected_value, 201, blog_attrs.except(:id))
|
238
|
+
returned = blog.by_users(user_id, &:save!)
|
239
|
+
check_returned_object(BlogApi::Blog, expected_value, blog)
|
240
|
+
expect(returned).to eq(blog)
|
241
|
+
expect(blog.id).to eq(blog_id)
|
242
|
+
expect(stub).to have_been_requested
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'PUTs data in parent resource context when id is not nil' do
|
246
|
+
blog = BlogApi::Blog.new(id: blog_id, title: 'hello')
|
247
|
+
user_id = 'ux345'
|
248
|
+
|
249
|
+
stub = req(:put, "/users/#{user_id}/blogs/#{blog_id}", nil, 204, blog_attrs.except(:id))
|
250
|
+
returned = blog.by_users(user_id, &:save!)
|
251
|
+
expect(returned).to eq(blog)
|
252
|
+
expect(blog.id).to eq(blog_id)
|
253
|
+
expect(stub).to have_been_requested
|
254
|
+
end
|
255
|
+
end
|
226
256
|
end
|
227
257
|
|
228
258
|
context '#destroy!' do
|
229
259
|
it 'DELETEs data when id is not nil' do
|
230
|
-
blog
|
231
|
-
stub
|
260
|
+
blog = BlogApi::Blog.new(id: 323, title: 'hello')
|
261
|
+
stub = req(:delete, "/blogs/#{blog.id}", '', 204)
|
262
|
+
|
232
263
|
returned = blog.destroy!
|
233
264
|
expect(returned).to eq(blog)
|
234
265
|
expect(stub).to have_been_requested
|
235
266
|
end
|
236
|
-
it 'not DELETE data when id is nil' do
|
237
|
-
blog = BlogApi::Blog.new(id: nil, title: 'hello')
|
238
|
-
stub = req(:delete, '/blogs', '', 204)
|
239
|
-
returned = blog.destroy!
|
240
|
-
expect(returned).to eq(blog)
|
241
|
-
expect(stub).to_not have_been_requested
|
242
|
-
end
|
243
267
|
end
|
244
268
|
|
245
269
|
context '#submit!' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chaker Nakhli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: simple-hmac
|