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 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