api-resource 0.5.5 → 0.6.0

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: 6e0b3e5f0c0998f062cdd1657844dacc73edb38f
4
- data.tar.gz: 6dcbfddbc124e80bd22f047eec0de88c118bcb36
3
+ metadata.gz: e3dab8e5d2531d7f27d4034f61818e59037d4b23
4
+ data.tar.gz: b2a85b96d4c0a9bcfdacef705f89bf6c355b626f
5
5
  SHA512:
6
- metadata.gz: 29a70f2851bf3dce62764ce8ada3bd055e909b028ea470275340d187c8431c8c5853737c6807209390d7178e2785a74e85374cdf99f691fbe0ef157453434331
7
- data.tar.gz: e5b8bfb0c3d49809300f25b013d865b9cdb7818dd9ab3a33cc92aba17b2e410dbbd35d01fa351d5b7ebe279d01c57a90229c5134ccc70394346b868a5462d8ac
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 :submitted_attributes_filter
26
- class_attribute :log
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.submitted_attributes_filter = block if block_given?
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({}, :get)
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: 500 }.merge(options)
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, verb=:get)
81
- result = client(verb, options, resource_path)
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.class.client(:delete, id, resource_path) if self.id
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
- with_parent_resource(args[0], $1) unless args.empty?
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 self.with_parent_resource(parent_resource_id, parent_resource_name)
181
- parent_resource_name = parent_resource_name.pluralize
182
- child_resource_path = resource_path
183
- Class.new(self) do
184
- self.resource_path = build_url(parent_resource_name, parent_resource_id, child_resource_path)
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 self.client(verb, params, *paths)
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: verb, headers: headers }
203
- if verb == :get
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
- logger << result
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.logger=(param)
224
- self.log = create_log(param)
251
+ def self.log=(param)
252
+ self.logger = create_log(param)
225
253
  end
226
254
 
227
- def self.logger
228
- self.log ||= Class.new do
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
 
@@ -1,3 +1,3 @@
1
1
  module ApiResource
2
- VERSION = '0.5.5'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -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
- it 'POSTs data when id is nil' do
206
- blog = BlogApi::Blog.new(title: 'hello')
207
- expect(blog.id).to be_nil
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
- stub = req(:post, '/blogs', expected_value, 201, { title: 'hello' })
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
- stub = req(:put, '/blogs', nil, 204, id: blog_id.to_s, title: 'hello')
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 = BlogApi::Blog.new(id: 323, title: 'hello')
231
- stub = req(:delete, '/blogs', '', 204)
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.5.5
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-03-30 00:00:00.000000000 Z
11
+ date: 2015-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple-hmac