crud-service 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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