crud-service 0.0.9 → 0.1.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,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OWU4YWI0ZDc4OWRiYTU2YjhjYjg5MzFjNWM2MDg2MjJhZjQwYzU4YQ==
5
- data.tar.gz: !binary |-
6
- NDFkMmFkZmZmODQ3YjVhNzA3Y2M4MzgwMjgzYzg2NGU1MzAxYTM4YQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YTI3MDU2ZmU4MTc1ZDU2MWM3NmM1MGFiYTIwMDYzYWEzNWY3MGQ1MzY3YjBh
10
- Y2Q5NWEyYjczZmIzZmMzZGY0Mjg5MGEzMTViOWE4NGRiODc1NThjZjA5NGE0
11
- MzcyZmQxMmIxZDE2ZmZhMGY3OGY1NzU4ZjE0ZDczMTE4NGQ4ZWQ=
12
- data.tar.gz: !binary |-
13
- YTQzOGZlMjM2MDkxODAzZDU0ZmMyZDM1MzQ2Njc0ZTM2MTg1MmQ4ZmI4MTAw
14
- NzVmZTkzNDJmMTRlNjBlNDQ2YmQ1MTY1YzE0MmI1MzljZTZhZjE4ZWJkODky
15
- N2I0MjIwMWE0M2IwZjA2YjMxMmU2NzRhODhjNWM3MWY3ZDZiNjI=
2
+ SHA1:
3
+ metadata.gz: 7790c1877ec4d0783a3813a172928fb84e8611c0
4
+ data.tar.gz: 53ec5d4ae333d795cf0aaa1a47b7211ce79256e2
5
+ SHA512:
6
+ metadata.gz: 2900ea911d11cb0f7c2ab0c00280a656c135216309eee42397350ee06e0f072db7d2a71554d54d98b7ea071165b23a10b2073c798c463115d133d8f450478b32
7
+ data.tar.gz: 22124825d383be131bc3f58ac0f0eef5a9cadcf4f886e5548cf053c1c3bcc7e9b35e24a7174ba9b6529ab5dd5317bd984ae1c798b03b3e66c8787c7028bea1ba
@@ -1,3 +1,6 @@
1
- require "api"
2
- require "dal"
3
- require "service"
1
+ files = [
2
+ 'version',
3
+ 'api',
4
+ 'dal',
5
+ 'service',
6
+ ].each { |file| require "#{File.dirname(__FILE__)}/crud-service/#{file}" }
@@ -0,0 +1,152 @@
1
+ module CrudService
2
+ # This mixin provides a static methods to configure a sinatra class with the
3
+ # provided resource name, service and api_options
4
+ module Api
5
+ # Set up full CRUD API functionality on the given resource
6
+ def crud_api(resource_name, service_name, primary_key_name, api_options = {})
7
+ api_options = get_defaults(api_options)
8
+
9
+ crud_options(resource_name, api_options) if api_options[:enable_options]
10
+
11
+ if api_options[:enable_write]
12
+ crud_post(resource_name, service_name, primary_key_name, api_options) if api_options[:enable_post]
13
+ crud_put(resource_name, service_name, primary_key_name, api_options) if api_options[:enable_put]
14
+ crud_delete(resource_name, service_name, primary_key_name, api_options) if api_options[:enable_delete]
15
+ end
16
+
17
+ if api_options[:enable_read]
18
+ crud_get(resource_name, service_name, primary_key_name, api_options) if api_options[:enable_get]
19
+ crud_get_all(resource_name, service_name, api_options) if api_options[:enable_get_all]
20
+ end
21
+ end
22
+
23
+ # Set up OPTIONS functionality on the given resource
24
+ def crud_options(resource_name, api_options = {})
25
+ api_options = get_defaults(api_options)
26
+ options '/'+resource_name do
27
+ 204
28
+ end
29
+ end
30
+
31
+ # Set up UPDATE/put functionality on the given resource
32
+ def crud_put(resource_name, service_name, primary_key_name, api_options = {})
33
+ api_options = get_defaults(api_options)
34
+ put '/'+resource_name+'/:'+primary_key_name do
35
+ service = settings.send(service_name)
36
+
37
+ # Must Exist
38
+ return 404 unless service.exists_by_primary_key?(params[primary_key_name.to_sym])
39
+
40
+ # Get The Data
41
+ begin
42
+ data = JSON.parse(request.body.read)
43
+ rescue Exception => e
44
+ return 422
45
+ end
46
+
47
+ # Valid Update?
48
+ return 422 unless service.valid_update?(data)
49
+
50
+ # Do Update
51
+ record = service.update_by_primary_key(params[primary_key_name.to_sym],data)
52
+
53
+ # Other Error
54
+ return 500 if record.nil?
55
+
56
+ # Return new Region
57
+ JSON.fast_generate record
58
+ end
59
+ end
60
+
61
+ # Set up GET/get_one functionality on the given resource
62
+ def crud_get(resource_name, service_name, primary_key_name, api_options = {})
63
+ api_options = get_defaults(api_options)
64
+ get '/'+resource_name+'/:'+primary_key_name do
65
+ service = settings.send(service_name)
66
+
67
+ sanitize_params(params)
68
+ return 400 unless service.valid_query?(params)
69
+
70
+ record = service.get_one_by_query(params)
71
+ return 404 if record.nil?
72
+ JSON.fast_generate record
73
+ end
74
+ end
75
+
76
+ # Set up GET/get_all functionality on the given resource
77
+ def crud_get_all(resource_name, service_name, api_options = {})
78
+ api_options = get_defaults(api_options)
79
+ get '/'+resource_name do
80
+ service = settings.send(service_name)
81
+
82
+ sanitize_params(params)
83
+ # Check query validity
84
+ return 400 unless service.valid_query?(params)
85
+
86
+ # Return Regions on Query
87
+ JSON.fast_generate service.get_all_by_query(params)
88
+ end
89
+ end
90
+
91
+ # Set up DELETE functionality on the given resource
92
+ def crud_delete(resource_name, service_name, primary_key_name, api_options = {})
93
+ api_options = get_defaults(api_options)
94
+ delete '/'+resource_name+'/:'+primary_key_name do
95
+ service = settings.send(service_name)
96
+
97
+ # Must Exist
98
+ return 404 unless service.exists_by_primary_key?(params[primary_key_name.to_sym])
99
+
100
+ # Do Delete
101
+ return 500 unless service.delete_by_primary_key(params[primary_key_name.to_sym])
102
+
103
+ 204
104
+ end
105
+ end
106
+
107
+ # Set up POST/insert functionality on the given resource
108
+ def crud_post(resource_name, service_name, primary_key_name, api_options = {})
109
+ api_options = get_defaults(api_options)
110
+ post '/'+resource_name do
111
+ service = settings.send(service_name)
112
+
113
+ # Get The data
114
+ begin
115
+ data = JSON.parse(request.body.read)
116
+ rescue Exception => e
117
+ return 422
118
+ end
119
+
120
+ # Valid POST?
121
+ return 422 unless service.valid_insert?(data)
122
+
123
+ # Already Exists?
124
+ return 409 if service.exists_by_primary_key?(data[primary_key_name])
125
+
126
+ # Do Insert
127
+ record = service.insert(data)
128
+
129
+ # Other Error
130
+ return 500 if record.nil?
131
+
132
+ # Output new record
133
+ JSON.fast_generate record
134
+ end
135
+ end
136
+
137
+ # Return the given options with defaults set
138
+ def get_defaults(api_options)
139
+ defaults = {
140
+ :enable_read => true,
141
+ :enable_write => true,
142
+ :enable_options => true,
143
+ :enable_get_all => true,
144
+ :enable_get => true,
145
+ :enable_post => true,
146
+ :enable_put => true,
147
+ :enable_delete => true,
148
+ }
149
+ api_options.merge!(defaults) { |key, v1, v2| v1 }
150
+ end
151
+ end
152
+ end
@@ -1,4 +1,3 @@
1
- require 'json'
2
1
  require 'mysql2'
3
2
 
4
3
  module CrudService
@@ -7,7 +6,24 @@ module CrudService
7
6
  # Your should extend this class to provide configuration for your dal, please see
8
7
  # the README file at http://github.com/tomcully/crud-service
9
8
  class Dal
10
- attr_accessor :mysql, :memcache, :log, :table_name, :fields, :relations, :primary_key, :auto_primary_key, :cache_prefix
9
+ # The DB layer to use, e.g. an instance of Mysql2::Client
10
+ attr_accessor :mysql
11
+ # The Memcache layer to use, e.g. an instance of Dalli::Client
12
+ attr_accessor :memcache
13
+ # The logger to use, e.g. an instance of Console::Logger
14
+ attr_accessor :log
15
+ # The DB table name
16
+ attr_accessor :table_name
17
+ # A Hash of table fields (See README)
18
+ attr_accessor :fields
19
+ # A Hash of table relations (See README)
20
+ attr_accessor :relations
21
+ # The primary key name
22
+ attr_accessor :primary_key
23
+ # If true, the primary key values are assigned by the DB layer
24
+ attr_accessor :auto_primary_key
25
+ # The memcache key prefix for this DAL
26
+ attr_accessor :cache_prefix
11
27
 
12
28
  # Create an instance.
13
29
  def initialize(mysql, memcache = nil, log)
@@ -105,6 +121,7 @@ module CrudService
105
121
  where.chomp(' AND ')
106
122
  end
107
123
 
124
+ # Build a simple where clause from the given query with the given table/db namespace
108
125
  def build_where_ns(query,ns)
109
126
  where = ""
110
127
  query.each_pair do |k, v|
@@ -214,6 +231,7 @@ module CrudService
214
231
  map_to_hash_by_primary_key(get_all_by_query(query))
215
232
  end
216
233
 
234
+ # Map in the included relations to each of the supplied result rows
217
235
  def map_in_included_relations!(result, query)
218
236
  dat = get_relation_data_as_hash(query)
219
237
  result.each do |res|
@@ -230,7 +248,7 @@ module CrudService
230
248
 
231
249
  # Get data for included relations for a query
232
250
  def get_relation_data_as_hash(query)
233
- return {} if @relations.nil?
251
+ return {} if @relations.nil? or @relations.empty?
234
252
 
235
253
  includes = get_includes(query)
236
254
 
@@ -248,6 +266,7 @@ module CrudService
248
266
  reldata
249
267
  end
250
268
 
269
+ # Remove the given key from each record in the supplied hash
251
270
  def remove_key_from_hash_of_arrays!(hash,key)
252
271
  hash.each do |name,arr|
253
272
  arr.each do |record|
@@ -311,6 +330,7 @@ module CrudService
311
330
  return get_has_many_through_relation_query_sql(relation, query)
312
331
  else
313
332
  @log.error("Relation type #{relation[:type]} undefined!")
333
+ nil
314
334
  end
315
335
  end
316
336
 
@@ -354,7 +374,7 @@ module CrudService
354
374
  when :has_many_through
355
375
  return [@table_name, relation[:table], relation[:link_table]].sort
356
376
  else
357
- throw "Unknown Relation type #{relation.type}"
377
+ raise "Unknown Relation type #{relation[:type]}"
358
378
  end
359
379
  end
360
380
 
@@ -427,7 +447,7 @@ module CrudService
427
447
  queryresult = @mysql.query(query)
428
448
  rescue Exception => e
429
449
  @log.error("#{e}")
430
- return false
450
+ return nil
431
451
  end
432
452
 
433
453
  expire_table_cache(get_all_related_tables)
@@ -1,6 +1,12 @@
1
1
  module CrudService
2
+ # Service provides a generic mapping layer between the API and the DAL.
3
+ # You should extend this class, or provide a class with the same interface,
4
+ # to implement service level functionality, or support REST-like RPC.
2
5
  class Service
3
- attr_accessor :dal, :log
6
+ # The DAL layer to use, e.g. an instance of CrudService::DAL
7
+ attr_accessor :dal
8
+ # The logger to use, e.g. an instance of Console::Logger
9
+ attr_accessor :log
4
10
 
5
11
  # Instantiate a service with the specified DAL and logger.
6
12
  def initialize(dal, log)
@@ -0,0 +1,5 @@
1
+ # The `crud-service` module provides classes and mixins to implement a basic JSON CRUD service using Sinatra, MySQL and memcached.
2
+ module CrudService
3
+ # The version of CrudService
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,609 @@
1
+ require "spec_helper"
2
+
3
+ class TestAPI
4
+ include CrudService::Api
5
+ end
6
+
7
+ describe CrudService::Api do
8
+
9
+ describe '#get_defaults' do
10
+
11
+ it 'should produce correct fields' do
12
+ inst = TestAPI.new
13
+
14
+ mock_opts = {
15
+ :enable_read=>true,
16
+ :enable_write=>true,
17
+ :enable_options=>true,
18
+ :enable_get_all=>true,
19
+ :enable_get=>true,
20
+ :enable_post=>true,
21
+ :enable_put=>true,
22
+ :enable_delete=>true
23
+ }
24
+
25
+ expect(inst.get_defaults({})).to eq(mock_opts)
26
+ end
27
+
28
+ it 'should not overwrite existing fields' do
29
+ inst = TestAPI.new
30
+
31
+ mock_opts = {
32
+ :enable_read=>true,
33
+ :enable_write=>true,
34
+ :enable_options=>false,
35
+ :enable_get_all=>true,
36
+ :enable_get=>true,
37
+ :enable_post=>true,
38
+ :enable_put=>true,
39
+ :enable_delete=>true
40
+ }
41
+
42
+ expect(inst.get_defaults({:enable_options=>false})).to eq(mock_opts)
43
+ end
44
+
45
+ end
46
+ describe '#crud_api' do
47
+ it 'should call correct methods in correct order for defaults' do
48
+ mock_opts = {
49
+ :enable_read=>true,
50
+ :enable_write=>true,
51
+ :enable_options=>true,
52
+ :enable_get_all=>true,
53
+ :enable_get=>true,
54
+ :enable_post=>true,
55
+ :enable_put=>true,
56
+ :enable_delete=>true
57
+ }
58
+
59
+ inst = TestAPI.new
60
+
61
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
62
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
63
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
64
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
65
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
66
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
67
+
68
+ inst.crud_api(1,2,3,{})
69
+ end
70
+
71
+ it 'should not call write methods if enable_write is false' do
72
+ mock_opts = { :enable_write=>false, :enable_post=>true, :enable_put=>true, :enable_delete=>true }
73
+
74
+ inst = TestAPI.new
75
+
76
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
77
+ expect(inst).not_to receive(:crud_post).with(1,2,3,mock_opts)
78
+ expect(inst).not_to receive(:crud_put).with(1,2,3,mock_opts)
79
+ expect(inst).not_to receive(:crud_delete).with(1,2,3,mock_opts)
80
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
81
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
82
+
83
+ inst.crud_api(1,2,3,mock_opts)
84
+ end
85
+
86
+ it 'should not call read methods if enable_read is false' do
87
+ mock_opts = { :enable_read=>false, :enable_get=>true, :enable_get_all=>true }
88
+
89
+ inst = TestAPI.new
90
+
91
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
92
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
93
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
94
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
95
+ expect(inst).not_to receive(:crud_get).with(1,2,3,mock_opts)
96
+ expect(inst).not_to receive(:crud_get_all).with(1,2,mock_opts)
97
+
98
+ inst.crud_api(1,2,3,mock_opts)
99
+ end
100
+
101
+ it 'should not call crud_post method if enable_post is false' do
102
+ mock_opts = { :enable_read=>true, :enable_write=>true, :enable_post=>false }
103
+
104
+ inst = TestAPI.new
105
+
106
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
107
+ expect(inst).not_to receive(:crud_post).with(1,2,3,mock_opts)
108
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
109
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
110
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
111
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
112
+
113
+ inst.crud_api(1,2,3,mock_opts)
114
+ end
115
+
116
+ it 'should not call crud_put method if enable_put is false' do
117
+ mock_opts = { :enable_read=>true, :enable_write=>true, :enable_put=>false }
118
+
119
+ inst = TestAPI.new
120
+
121
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
122
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
123
+ expect(inst).not_to receive(:crud_put).with(1,2,3,mock_opts)
124
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
125
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
126
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
127
+
128
+ inst.crud_api(1,2,3,mock_opts)
129
+ end
130
+
131
+ it 'should not call crud_delete method if enable_delete is false' do
132
+ mock_opts = { :enable_read=>true, :enable_write=>true, :enable_delete=>false }
133
+
134
+ inst = TestAPI.new
135
+
136
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
137
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
138
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
139
+ expect(inst).not_to receive(:crud_delete).with(1,2,3,mock_opts)
140
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
141
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
142
+
143
+ inst.crud_api(1,2,3,mock_opts)
144
+ end
145
+
146
+ it 'should not call crud_get method if enable_get is false' do
147
+ mock_opts = { :enable_read=>true, :enable_write=>true, :enable_get=>false }
148
+
149
+ inst = TestAPI.new
150
+
151
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
152
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
153
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
154
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
155
+ expect(inst).not_to receive(:crud_get).with(1,2,3,mock_opts)
156
+ expect(inst).to receive(:crud_get_all).with(1,2,mock_opts)
157
+
158
+ inst.crud_api(1,2,3,mock_opts)
159
+ end
160
+
161
+ it 'should not call crud_get_all method if enable_get_all is false' do
162
+ mock_opts = { :enable_read=>true, :enable_write=>true, :enable_get_all=>false }
163
+
164
+ inst = TestAPI.new
165
+
166
+ expect(inst).to receive(:crud_options).with(1,mock_opts)
167
+ expect(inst).to receive(:crud_post).with(1,2,3,mock_opts)
168
+ expect(inst).to receive(:crud_put).with(1,2,3,mock_opts)
169
+ expect(inst).to receive(:crud_delete).with(1,2,3,mock_opts)
170
+ expect(inst).to receive(:crud_get).with(1,2,3,mock_opts)
171
+ expect(inst).not_to receive(:crud_get_all).with(1,2,mock_opts)
172
+
173
+ inst.crud_api(1,2,3,mock_opts)
174
+ end
175
+ end
176
+
177
+ describe '#crud_options' do
178
+ it 'should call get_defaults and options' do
179
+ mock_opts = { :enable_get_all=>false }
180
+
181
+ inst = TestAPI.new
182
+
183
+ expect(inst).to receive(:get_defaults).with(mock_opts)
184
+ expect(inst).to receive(:options) do |resname, &block|
185
+ expect(resname).to eq('/resource')
186
+ expect(block.call).to eq(204)
187
+ end
188
+
189
+ inst.crud_options('resource', mock_opts)
190
+ end
191
+ end
192
+
193
+ describe '#crud_put' do
194
+ it 'should call get_defaults and options, return 404 if record doesnt exist' do
195
+ mock_opts = { :enable_get_all=>false }
196
+
197
+ inst = TestAPI.new
198
+
199
+ expect(inst).to receive(:get_defaults).with(mock_opts)
200
+ expect(inst).to receive(:put) do |resname, &block|
201
+ expect(resname).to eq('/resource/:primary')
202
+
203
+ settings = OpenStruct.new
204
+ service = OpenStruct.new
205
+ expect(inst).to receive(:settings).and_return(settings)
206
+ expect(settings).to receive(:send).with('service').and_return(service)
207
+
208
+ expect(inst).to receive(:params).and_return({:primary=>34567})
209
+ expect(service).to receive(:exists_by_primary_key?).with(34567).and_return(false)
210
+ block.call
211
+
212
+ end
213
+
214
+ expect(inst.crud_put('resource','service','primary',mock_opts)).to eq(404)
215
+ end
216
+
217
+ it 'should call get_defaults and options, return 422 if JSON parse fails' do
218
+ mock_opts = { :enable_get_all=>false }
219
+
220
+ inst = TestAPI.new
221
+
222
+ expect(inst).to receive(:get_defaults).with(mock_opts)
223
+ expect(inst).to receive(:put) do |resname, &block|
224
+ expect(resname).to eq('/resource/:primary')
225
+
226
+ settings = OpenStruct.new
227
+ service = OpenStruct.new
228
+ expect(inst).to receive(:settings).and_return(settings)
229
+ expect(settings).to receive(:send).with('service').and_return(service)
230
+
231
+ expect(inst).to receive(:params).and_return({:primary=>34567})
232
+ expect(service).to receive(:exists_by_primary_key?).with(34567).and_return(true)
233
+
234
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1'})})
235
+ expect(inst).to receive(:request).and_return(request)
236
+
237
+ block.call
238
+ end
239
+
240
+ expect(inst.crud_put('resource','service','primary',mock_opts)).to eq(422)
241
+ end
242
+
243
+ it 'should call get_defaults and options, return 500 if update fails' do
244
+ mock_opts = { :enable_get_all=>false }
245
+
246
+ inst = TestAPI.new
247
+
248
+ expect(inst).to receive(:get_defaults).with(mock_opts)
249
+ expect(inst).to receive(:put) do |resname, &block|
250
+ expect(resname).to eq('/resource/:primary')
251
+
252
+ settings = OpenStruct.new
253
+ service = OpenStruct.new
254
+ expect(inst).to receive(:settings).and_return(settings)
255
+ expect(settings).to receive(:send).with('service').and_return(service)
256
+
257
+ expect(inst).to receive(:params).twice.and_return({:primary=>34567})
258
+ expect(service).to receive(:exists_by_primary_key?).with(34567).and_return(true)
259
+
260
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1}'})})
261
+ expect(inst).to receive(:request).and_return(request)
262
+
263
+ expect(service).to receive(:valid_update?).with({"one"=>1}).and_return(true)
264
+
265
+ expect(service).to receive(:update_by_primary_key).with(34567, {"one"=>1}).and_return(nil)
266
+
267
+ block.call
268
+ end
269
+
270
+ expect(inst.crud_put('resource','service','primary',mock_opts)).to eq(500)
271
+ end
272
+
273
+ it 'should call get_defaults and options, return JSON string of record' do
274
+ mock_opts = { :enable_get_all=>false }
275
+
276
+ inst = TestAPI.new
277
+
278
+ expect(inst).to receive(:get_defaults).with(mock_opts)
279
+ expect(inst).to receive(:put) do |resname, &block|
280
+ expect(resname).to eq('/resource/:primary')
281
+
282
+ settings = OpenStruct.new
283
+ service = OpenStruct.new
284
+ expect(inst).to receive(:settings).and_return(settings)
285
+ expect(settings).to receive(:send).with('service').and_return(service)
286
+
287
+ expect(inst).to receive(:params).twice.and_return({:primary=>34567})
288
+ expect(service).to receive(:exists_by_primary_key?).with(34567).and_return(true)
289
+
290
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1}'})})
291
+ expect(inst).to receive(:request).and_return(request)
292
+
293
+ expect(service).to receive(:valid_update?).with({"one"=>1}).and_return(true)
294
+
295
+ expect(service).to receive(:update_by_primary_key).with(34567, {"one"=>1}).and_return({"two"=>2})
296
+
297
+ block.call
298
+ end
299
+
300
+ expect(inst.crud_put('resource','service','primary',mock_opts)).to eq('{"two":2}')
301
+ end
302
+ end
303
+
304
+ describe '#crud_get' do
305
+ it 'should call get_defaults and options, return 400 if bad query' do
306
+ mock_opts = { :enable_get_all=>false }
307
+
308
+ inst = TestAPI.new
309
+
310
+ expect(inst).to receive(:get_defaults).with(mock_opts)
311
+ expect(inst).to receive(:get) do |resname, &block|
312
+ expect(resname).to eq('/resource/:primary')
313
+
314
+ service = OpenStruct.new
315
+ settings = OpenStruct.new("service_name" => service)
316
+ params = OpenStruct.new
317
+ expect(inst).to receive(:settings).and_return(settings)
318
+ expect(inst).to receive(:params).twice.and_return(params)
319
+
320
+ expect(inst).to receive(:sanitize_params).with(params)
321
+ expect(service).to receive(:valid_query?).with(params).and_return(false)
322
+
323
+ block.call
324
+ end
325
+
326
+ expect(inst.crud_get('resource','service_name','primary',mock_opts)).to eq(400)
327
+ end
328
+
329
+ it 'should call get_defaults and options, return 404 if not found' do
330
+ mock_opts = { :enable_get_all=>false }
331
+
332
+ inst = TestAPI.new
333
+
334
+ expect(inst).to receive(:get_defaults).with(mock_opts)
335
+ expect(inst).to receive(:get) do |resname, &block|
336
+ expect(resname).to eq('/resource/:primary')
337
+
338
+ service = OpenStruct.new
339
+ settings = OpenStruct.new("service_name" => service)
340
+ params = OpenStruct.new
341
+ expect(inst).to receive(:settings).and_return(settings)
342
+ expect(inst).to receive(:params).thrice.and_return(params)
343
+
344
+ expect(inst).to receive(:sanitize_params).with(params)
345
+ expect(service).to receive(:valid_query?).with(params).and_return(true)
346
+
347
+ expect(service).to receive(:get_one_by_query).with(params).and_return(nil)
348
+
349
+ block.call
350
+ end
351
+
352
+ expect(inst.crud_get('resource','service_name','primary',mock_opts)).to eq(404)
353
+ end
354
+
355
+ it 'should call get_defaults and options, return 404 if not found' do
356
+ mock_opts = { :enable_get_all=>false }
357
+
358
+ inst = TestAPI.new
359
+
360
+ expect(inst).to receive(:get_defaults).with(mock_opts)
361
+ expect(inst).to receive(:get) do |resname, &block|
362
+ expect(resname).to eq('/resource/:primary')
363
+
364
+ service = OpenStruct.new
365
+ settings = OpenStruct.new("service_name" => service)
366
+ params = OpenStruct.new
367
+ expect(inst).to receive(:settings).and_return(settings)
368
+ expect(inst).to receive(:params).thrice.and_return(params)
369
+
370
+ expect(inst).to receive(:sanitize_params).with(params)
371
+ expect(service).to receive(:valid_query?).with(params).and_return(true)
372
+
373
+ expect(service).to receive(:get_one_by_query).with(params).and_return({"three"=>3})
374
+
375
+ block.call
376
+ end
377
+
378
+ expect(inst.crud_get('resource','service_name','primary',mock_opts)).to eq('{"three":3}')
379
+ end
380
+ end
381
+
382
+ describe '#crud_get_all' do
383
+ it 'should call get_defaults and options, return 400 if bad query' do
384
+ mock_opts = { :enable_get_all=>false }
385
+
386
+ inst = TestAPI.new
387
+
388
+ expect(inst).to receive(:get_defaults).with(mock_opts)
389
+ expect(inst).to receive(:get) do |resname, &block|
390
+ expect(resname).to eq('/resource')
391
+
392
+ service = OpenStruct.new
393
+ settings = OpenStruct.new("service_name" => service)
394
+ params = OpenStruct.new
395
+ expect(inst).to receive(:settings).and_return(settings)
396
+ expect(inst).to receive(:params).twice.and_return(params)
397
+
398
+ expect(inst).to receive(:sanitize_params).with(params)
399
+ expect(service).to receive(:valid_query?).with(params).and_return(false)
400
+
401
+ block.call
402
+ end
403
+
404
+ expect(inst.crud_get_all('resource','service_name',mock_opts)).to eq(400)
405
+ end
406
+
407
+ it 'should call get_defaults and options, return JSON string from records' do
408
+ mock_opts = { :enable_get_all=>false }
409
+
410
+ inst = TestAPI.new
411
+
412
+ expect(inst).to receive(:get_defaults).with(mock_opts)
413
+ expect(inst).to receive(:get) do |resname, &block|
414
+ expect(resname).to eq('/resource')
415
+
416
+ service = OpenStruct.new
417
+ settings = OpenStruct.new("service_name" => service)
418
+ params = OpenStruct.new
419
+ expect(inst).to receive(:settings).and_return(settings)
420
+ expect(inst).to receive(:params).thrice.and_return(params)
421
+
422
+ expect(inst).to receive(:sanitize_params).with(params)
423
+ expect(service).to receive(:valid_query?).with(params).and_return(true)
424
+
425
+ expect(service).to receive(:get_all_by_query).with(params).and_return([{"three"=>3}])
426
+
427
+ block.call
428
+ end
429
+
430
+ expect(inst.crud_get_all('resource','service_name',mock_opts)).to eq('[{"three":3}]')
431
+ end
432
+ end
433
+
434
+ describe '#crud_delete' do
435
+ it 'should call get_defaults and options, return 404 if not found' do
436
+ mock_opts = { :enable_get_all=>false }
437
+
438
+ inst = TestAPI.new
439
+
440
+ expect(inst).to receive(:get_defaults).with(mock_opts)
441
+ expect(inst).to receive(:delete) do |resname, &block|
442
+ expect(resname).to eq('/resource/:primary')
443
+
444
+ service = OpenStruct.new
445
+ settings = OpenStruct.new("service_name" => service)
446
+ params = OpenStruct.new({"primary"=>6})
447
+ expect(inst).to receive(:settings).and_return(settings)
448
+ expect(inst).to receive(:params).and_return(params)
449
+
450
+ expect(service).to receive(:exists_by_primary_key?).with(6).and_return(false)
451
+
452
+ block.call
453
+ end
454
+
455
+ expect(inst.crud_delete('resource','service_name','primary',mock_opts)).to eq(404)
456
+ end
457
+
458
+ it 'should call get_defaults and options, return 500 if record failed to delete' do
459
+ mock_opts = { :enable_get_all=>false }
460
+
461
+ inst = TestAPI.new
462
+
463
+ expect(inst).to receive(:get_defaults).with(mock_opts)
464
+ expect(inst).to receive(:delete) do |resname, &block|
465
+ expect(resname).to eq('/resource/:primary')
466
+
467
+ service = OpenStruct.new
468
+ settings = OpenStruct.new("service_name" => service)
469
+ params = OpenStruct.new({"primary"=>6})
470
+ expect(inst).to receive(:settings).and_return(settings)
471
+ expect(inst).to receive(:params).twice.and_return(params)
472
+
473
+ expect(service).to receive(:exists_by_primary_key?).with(6).and_return(true)
474
+ expect(service).to receive(:delete_by_primary_key).with(6).and_return(false)
475
+
476
+ block.call
477
+ end
478
+
479
+ expect(inst.crud_delete('resource','service_name','primary',mock_opts)).to eq(500)
480
+ end
481
+
482
+ it 'should call get_defaults and options, return 204 if record deletes ok' do
483
+ mock_opts = { :enable_get_all=>false }
484
+
485
+ inst = TestAPI.new
486
+
487
+ expect(inst).to receive(:get_defaults).with(mock_opts)
488
+ expect(inst).to receive(:delete) do |resname, &block|
489
+ expect(resname).to eq('/resource/:primary')
490
+
491
+ service = OpenStruct.new
492
+ settings = OpenStruct.new("service_name" => service)
493
+ params = OpenStruct.new({"primary"=>6})
494
+ expect(inst).to receive(:settings).and_return(settings)
495
+ expect(inst).to receive(:params).twice.and_return(params)
496
+
497
+ expect(service).to receive(:exists_by_primary_key?).with(6).and_return(true)
498
+ expect(service).to receive(:delete_by_primary_key).with(6).and_return(true)
499
+
500
+ block.call
501
+ end
502
+
503
+ expect(inst.crud_delete('resource','service_name','primary',mock_opts)).to eq(204)
504
+ end
505
+ end
506
+
507
+ describe '#crud_put' do
508
+ it 'should call get_defaults and options, return 422 if body parse fails' do
509
+ mock_opts = { :enable_get_all=>false }
510
+
511
+ inst = TestAPI.new
512
+
513
+ expect(inst).to receive(:get_defaults).with(mock_opts)
514
+ expect(inst).to receive(:post) do |resname, &block|
515
+ expect(resname).to eq('/resource')
516
+
517
+ settings = OpenStruct.new
518
+ service = OpenStruct.new
519
+ expect(inst).to receive(:settings).and_return(settings)
520
+ expect(settings).to receive(:send).with('service').and_return(service)
521
+
522
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1'})})
523
+ expect(inst).to receive(:request).and_return(request)
524
+ block.call
525
+ end
526
+
527
+ expect(inst.crud_post('resource','service','primary',mock_opts)).to eq(422)
528
+ end
529
+
530
+ it 'should call get_defaults and options, return 422 if non valid insert' do
531
+ mock_opts = { :enable_get_all=>false }
532
+
533
+ inst = TestAPI.new
534
+
535
+ expect(inst).to receive(:get_defaults).with(mock_opts)
536
+ expect(inst).to receive(:post) do |resname, &block|
537
+ expect(resname).to eq('/resource')
538
+
539
+ settings = OpenStruct.new
540
+ service = OpenStruct.new
541
+ expect(inst).to receive(:settings).and_return(settings)
542
+ expect(settings).to receive(:send).with('service').and_return(service)
543
+
544
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1}'})})
545
+ expect(inst).to receive(:request).and_return(request)
546
+
547
+ expect(service).to receive(:valid_insert?).with({"one"=>1}).and_return(false)
548
+
549
+ block.call
550
+ end
551
+
552
+ expect(inst.crud_post('resource','service','one',mock_opts)).to eq(422)
553
+ end
554
+
555
+ it 'should call get_defaults and options, return 409 if pk already exists' do
556
+ mock_opts = { :enable_get_all=>false }
557
+
558
+ inst = TestAPI.new
559
+
560
+ expect(inst).to receive(:get_defaults).with(mock_opts)
561
+ expect(inst).to receive(:post) do |resname, &block|
562
+ expect(resname).to eq('/resource')
563
+
564
+ settings = OpenStruct.new
565
+ service = OpenStruct.new
566
+ expect(inst).to receive(:settings).and_return(settings)
567
+ expect(settings).to receive(:send).with('service').and_return(service)
568
+
569
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1}'})})
570
+ expect(inst).to receive(:request).and_return(request)
571
+
572
+ expect(service).to receive(:valid_insert?).with({"one"=>1}).and_return(true)
573
+ expect(service).to receive(:exists_by_primary_key?).with(1).and_return(true)
574
+
575
+ block.call
576
+ end
577
+
578
+ expect(inst.crud_post('resource','service','one',mock_opts)).to eq(409)
579
+ end
580
+
581
+ it 'should call get_defaults and options, return 500 if record fails to insert' do
582
+ mock_opts = { :enable_get_all=>false }
583
+
584
+ inst = TestAPI.new
585
+
586
+ expect(inst).to receive(:get_defaults).with(mock_opts)
587
+ expect(inst).to receive(:post) do |resname, &block|
588
+ expect(resname).to eq('/resource')
589
+
590
+ settings = OpenStruct.new
591
+ service = OpenStruct.new
592
+ expect(inst).to receive(:settings).and_return(settings)
593
+ expect(settings).to receive(:send).with('service').and_return(service)
594
+
595
+ request = OpenStruct.new({:body=>OpenStruct.new({:read => '{"one":1}'})})
596
+ expect(inst).to receive(:request).and_return(request)
597
+
598
+ expect(service).to receive(:valid_insert?).with({"one"=>1}).and_return(true)
599
+ expect(service).to receive(:exists_by_primary_key?).with(1).and_return(false)
600
+ expect(service).to receive(:insert).with({"one"=>1}).and_return({"five"=>5})
601
+
602
+ block.call
603
+ end
604
+
605
+ expect(inst.crud_post('resource','service','one',mock_opts)).to eq("{\"five\":5}")
606
+ end
607
+
608
+ end
609
+ end