crud-service 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/lib/generic_api.rb +87 -0
- data/lib/generic_dal.rb +471 -0
- data/lib/generic_log.rb +19 -0
- data/lib/generic_service.rb +57 -0
- metadata +48 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjQyZGYyOWQ0YWY1YjIyODkyNWQ1OTI5NGNkYzI4ZDA2OGUxZmE1Ng==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NmYxYjViMGZhMWM3OWVkMTlkYWQ1NWIxZmZkYTBjNzA1YTVmZGJhYw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZWMxNDdiMmY4YmY1YjlmNzJjNjZjYWE4NzhhN2U4Zjc1NTI0ZTI5NjYzZjVk
|
10
|
+
MGQzYmUzNDhjM2E4NGRhNDRjNDExNTYwY2I0ZTU1YzM4ZTk0NDM1MWYzNWNl
|
11
|
+
YWQ4MTZjNWZlODkyNDY1YTA4ZGJjMDBhYmM5YjUxMDBiODIyM2U=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzgyODJiNDFmMmYwN2YzODE5YzY1OTdhMzAzMGUzMDliYWYxYWRkNzg0N2Mz
|
14
|
+
OWRiNDRhOGYwMWYxNDZkODRmZjA4NTMzZmRhMDViN2JjYWU2NTcyNDI0NDY2
|
15
|
+
N2NiZWZmODIzMzIwY2Q2MzkwNzYwM2IzYTdhMDE4ZmVlYTA1MTg=
|
data/lib/generic_api.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module CrudService
|
2
|
+
class GenericApi
|
3
|
+
|
4
|
+
def self.crud_api(sinatra, service_name, name, primary_key_name)
|
5
|
+
|
6
|
+
sinatra.options '/'+name do
|
7
|
+
204
|
8
|
+
end
|
9
|
+
|
10
|
+
sinatra.post '/'+name do
|
11
|
+
# Get The data
|
12
|
+
begin
|
13
|
+
data = JSON.parse(request.body.read)
|
14
|
+
rescue Exception => e
|
15
|
+
return 400
|
16
|
+
end
|
17
|
+
|
18
|
+
# Valid POST?
|
19
|
+
return 400 unless settings.send(service_name).valid_insert?(data)
|
20
|
+
|
21
|
+
# Already Exists?
|
22
|
+
return 409 if settings.send(service_name).exists_by_primary_key?(data['code'])
|
23
|
+
|
24
|
+
# Do Insert
|
25
|
+
record = settings.send(service_name).insert(data)
|
26
|
+
|
27
|
+
# Other Error
|
28
|
+
return 500 if record == false
|
29
|
+
|
30
|
+
# Output new record
|
31
|
+
JSON.fast_generate record
|
32
|
+
end
|
33
|
+
|
34
|
+
sinatra.get '/'+name do
|
35
|
+
sanitize_params(params)
|
36
|
+
# Check query validity
|
37
|
+
return 400 unless settings.send(service_name).valid_query?(params)
|
38
|
+
|
39
|
+
# Return Regions on Query
|
40
|
+
JSON.fast_generate settings.send(service_name).get_all_by_query(params)
|
41
|
+
end
|
42
|
+
|
43
|
+
sinatra.get '/'+name+'/:'+primary_key_name do
|
44
|
+
sanitize_params(params)
|
45
|
+
return 400 unless settings.send(service_name).valid_query?(params)
|
46
|
+
|
47
|
+
record = settings.send(service_name).get_one_by_query(params)
|
48
|
+
return 404 if record.nil?
|
49
|
+
JSON.fast_generate record
|
50
|
+
end
|
51
|
+
|
52
|
+
sinatra.put '/'+name+'/:'+primary_key_name do
|
53
|
+
# Must Exist
|
54
|
+
return 404 unless settings.send(service_name).exists_by_primary_key?(params[:code])
|
55
|
+
|
56
|
+
# Get The Data
|
57
|
+
begin
|
58
|
+
data = JSON.parse(request.body.read)
|
59
|
+
rescue Exception => e
|
60
|
+
return 400
|
61
|
+
end
|
62
|
+
|
63
|
+
# Valid Update?
|
64
|
+
return 400 unless settings.send(service_name).valid_update?(data)
|
65
|
+
|
66
|
+
# Do Update
|
67
|
+
record = settings.send(service_name).update_by_primary_key(params[:code],data)
|
68
|
+
|
69
|
+
# Other Error
|
70
|
+
return 500 if record.nil?
|
71
|
+
|
72
|
+
# Return new Region
|
73
|
+
JSON.fast_generate record
|
74
|
+
end
|
75
|
+
|
76
|
+
sinatra.delete '/'+name+'/:'+primary_key_name do
|
77
|
+
# Must Exist
|
78
|
+
return 404 unless settings.send(service_name).exists_by_primary_key?(params[:code])
|
79
|
+
|
80
|
+
# Do Delete
|
81
|
+
return 400 unless settings.send(service_name).delete_by_primary_key(params[:code])
|
82
|
+
|
83
|
+
204
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/generic_dal.rb
ADDED
@@ -0,0 +1,471 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'mysql2'
|
3
|
+
|
4
|
+
module CrudService
|
5
|
+
class GenericDal
|
6
|
+
|
7
|
+
attr_accessor :mysql, :memcache, :log, :table_name, :fields, :relations, :primary_key
|
8
|
+
|
9
|
+
def initialize(mysql, memcache, log)
|
10
|
+
@mysql = mysql
|
11
|
+
@memcache = memcache
|
12
|
+
@log = log
|
13
|
+
end
|
14
|
+
|
15
|
+
# Execute a Query, reading from cache if enabled.
|
16
|
+
def cached_query(query, tables)
|
17
|
+
|
18
|
+
unless @memcache.nil?
|
19
|
+
|
20
|
+
unless tables.include? @table_name
|
21
|
+
tables.push @table_name
|
22
|
+
tables.sort!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get Table versions
|
26
|
+
table_versions = ""
|
27
|
+
|
28
|
+
tables.each do |table|
|
29
|
+
tbversion = @memcache.get(table+"-version")
|
30
|
+
if tbversion.nil?
|
31
|
+
expire_table_cache([table])
|
32
|
+
tbversion = 1
|
33
|
+
end
|
34
|
+
table_versions += table+"-"+tbversion.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the Query Hash
|
38
|
+
querymd5 = "geoservice-"+Digest::MD5.hexdigest(query+":"+table_versions)
|
39
|
+
|
40
|
+
# Read Cache and return if hit
|
41
|
+
results = @memcache.get querymd5
|
42
|
+
|
43
|
+
unless results.nil?
|
44
|
+
return results
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Perform the Query
|
50
|
+
begin
|
51
|
+
queryresult = @mysql.query(query)
|
52
|
+
rescue Exception => e
|
53
|
+
@log.error("#{e}")
|
54
|
+
return []
|
55
|
+
end
|
56
|
+
|
57
|
+
# Collate Results
|
58
|
+
results = []
|
59
|
+
unless queryresult.nil? or queryresult.count == 0
|
60
|
+
queryresult.each do |h|
|
61
|
+
results.push h
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
unless @memcache.nil?
|
66
|
+
# Write to Cache
|
67
|
+
@memcache.set querymd5, results
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return results
|
71
|
+
results
|
72
|
+
end
|
73
|
+
|
74
|
+
# Determine if all fields and includes in the query are available
|
75
|
+
def valid_query?(query)
|
76
|
+
return false if query.nil?
|
77
|
+
return true if query.keys.length == 0
|
78
|
+
|
79
|
+
query.each_key do |k|
|
80
|
+
return false if !@fields.has_key?(k) and k!='include' and k!='exclude'
|
81
|
+
end
|
82
|
+
|
83
|
+
get_includes(query).each do |k|
|
84
|
+
return false if !@fields.has_key?(k) and !@relations.has_key?(k)
|
85
|
+
end
|
86
|
+
|
87
|
+
get_excludes(query).each do |k|
|
88
|
+
return false if !@fields.has_key?(k)
|
89
|
+
end
|
90
|
+
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
# Build a simple where clause from the given query
|
95
|
+
def build_where(query)
|
96
|
+
where = ""
|
97
|
+
query.each_pair do |k, v|
|
98
|
+
if (k!='include' and k!='exclude')
|
99
|
+
where += "(`#{escape_str_field(k)}` #{build_equal_condition(v)}) AND "
|
100
|
+
end
|
101
|
+
end
|
102
|
+
where.chomp(' AND ')
|
103
|
+
end
|
104
|
+
|
105
|
+
def build_where_ns(query,ns)
|
106
|
+
where = ""
|
107
|
+
query.each_pair do |k, v|
|
108
|
+
if (k!='include' and k!='exclude')
|
109
|
+
where += "(`#{ns}`.`#{escape_str_field(k)}` #{build_equal_condition(v)}) AND "
|
110
|
+
end
|
111
|
+
end
|
112
|
+
where.chomp(' AND ')
|
113
|
+
end
|
114
|
+
|
115
|
+
# Build SQL INSERT fragment from data
|
116
|
+
def build_insert(data)
|
117
|
+
fields = ""
|
118
|
+
values = ""
|
119
|
+
data.each do |k,v|
|
120
|
+
fields += "`#{escape_str_field(k)}`, "
|
121
|
+
values += escape_value(v)+", "
|
122
|
+
end
|
123
|
+
"("+fields.chomp(', ')+") VALUES ("+values.chomp(', ')+")"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Build SQL UPDATE fragment from data
|
127
|
+
def build_update(data)
|
128
|
+
sql = ""
|
129
|
+
data.each do |k,v|
|
130
|
+
sql += "`#{escape_str_field(k)}` = "+escape_value(v)+", "
|
131
|
+
end
|
132
|
+
sql.chomp(", ")
|
133
|
+
end
|
134
|
+
|
135
|
+
# Return an escaped condition string for the value v
|
136
|
+
def build_equal_condition(v)
|
137
|
+
if v.nil?
|
138
|
+
# Nulls (nil)
|
139
|
+
return "IS NULL"
|
140
|
+
elsif v.kind_of? Integer or v.kind_of? Float
|
141
|
+
# Integers / Floats
|
142
|
+
return "= "+v.to_s
|
143
|
+
else
|
144
|
+
# Everything Else
|
145
|
+
return "= '#{@mysql.escape(v.to_s)}'"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get fields
|
150
|
+
def build_select_fields(fields,ns)
|
151
|
+
select = ""
|
152
|
+
fields.each do |k|
|
153
|
+
select += "`#{ns}`." unless ns.nil?
|
154
|
+
select += "`#{k}`,"
|
155
|
+
end
|
156
|
+
select.chomp(',')
|
157
|
+
end
|
158
|
+
|
159
|
+
# Get fields
|
160
|
+
def build_fields(query)
|
161
|
+
build_select_fields(@fields.keys - get_excludes(query),nil)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Get fields with a namespace
|
165
|
+
def build_fields_with_ns(query, ns)
|
166
|
+
build_select_fields(@fields.keys - get_excludes(query),ns)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Return an escaped SQL string for the value v
|
170
|
+
def escape_value(v)
|
171
|
+
if v.nil?
|
172
|
+
# Nulls (nil)
|
173
|
+
return "NULL"
|
174
|
+
elsif v.kind_of? Integer or v.kind_of? Float
|
175
|
+
# Integers / Floats
|
176
|
+
return v.to_s
|
177
|
+
else
|
178
|
+
# Everything Else
|
179
|
+
return "'#{@mysql.escape(v.to_s)}'"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Escape a field name
|
184
|
+
def escape_str_field(str)
|
185
|
+
str = str.to_s.sub(/\`/,'')
|
186
|
+
@mysql.escape(str)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Get one record via a query
|
190
|
+
def get_one(query)
|
191
|
+
res = get_all_by_query(query)
|
192
|
+
return nil if res.length == 0
|
193
|
+
res[0]
|
194
|
+
end
|
195
|
+
|
196
|
+
# Get All records via a query
|
197
|
+
def get_all_by_query(query)
|
198
|
+
qry = "SELECT #{build_fields(query)} FROM `#{@table_name}`"
|
199
|
+
where = build_where(query)
|
200
|
+
qry += " WHERE #{where}" unless where.length == 0
|
201
|
+
cached_query(qry,[@table_name])
|
202
|
+
end
|
203
|
+
|
204
|
+
# Get all records for this entity and map ids to a hash
|
205
|
+
def get_all_by_query_as_hash(query)
|
206
|
+
map_to_hash_by_primary_key(get_all_by_query(query))
|
207
|
+
end
|
208
|
+
|
209
|
+
def map_in_included_relations!(result, query)
|
210
|
+
dat = get_relation_data_as_hash(query)
|
211
|
+
result.each do |res|
|
212
|
+
dat.each do |name, lookup|
|
213
|
+
res[name] = lookup[res[@relations[name][:this_key]]]
|
214
|
+
if @relations[name][:type] == :has_one
|
215
|
+
res[name] = res[name][0] unless res[name].nil?
|
216
|
+
else
|
217
|
+
res[name] = [] if res[name].nil?
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Get data for included relations for a query
|
224
|
+
def get_relation_data_as_hash(query)
|
225
|
+
return {} if @relations.nil?
|
226
|
+
|
227
|
+
includes = get_includes(query)
|
228
|
+
|
229
|
+
reldata = {}
|
230
|
+
|
231
|
+
@relations.each do |name, relation|
|
232
|
+
unless includes.find_index(name).nil?
|
233
|
+
sql = get_relation_query_sql(relation, query)
|
234
|
+
tables = get_relation_tables(relation)
|
235
|
+
data = cached_query(sql,tables)
|
236
|
+
reldata[name] = map_to_hash_of_arrays_by_key(data,'_table_key')
|
237
|
+
remove_key_from_hash_of_arrays!(reldata[name],'_table_key')
|
238
|
+
end
|
239
|
+
end
|
240
|
+
reldata
|
241
|
+
end
|
242
|
+
|
243
|
+
def remove_key_from_hash_of_arrays!(hash,key)
|
244
|
+
hash.each do |name,arr|
|
245
|
+
arr.each do |record|
|
246
|
+
record.delete(key)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
hash
|
250
|
+
end
|
251
|
+
|
252
|
+
# Map a result array to a hash by primary key
|
253
|
+
def map_to_hash_by_primary_key(result)
|
254
|
+
hash = {}
|
255
|
+
|
256
|
+
result.each do |record|
|
257
|
+
hash[record[@primary_key]] = record
|
258
|
+
end
|
259
|
+
|
260
|
+
hash
|
261
|
+
end
|
262
|
+
|
263
|
+
# Map a result array to a hash of arrays by a specific key
|
264
|
+
def map_to_hash_of_arrays_by_key(result,key)
|
265
|
+
res = {}
|
266
|
+
|
267
|
+
result.each do |record|
|
268
|
+
res[record[key]] = [] unless res.has_key?(record[key])
|
269
|
+
res[record[key]].push record
|
270
|
+
end
|
271
|
+
|
272
|
+
res
|
273
|
+
end
|
274
|
+
|
275
|
+
# Add a field to each record from map using another field as a key
|
276
|
+
def add_field_from_map!(result, map, field_name, key_name)
|
277
|
+
out = []
|
278
|
+
result.each do |record|
|
279
|
+
record[field_name] = map[record[key_name]] if map.has_key?(record[key_name])
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Get includes
|
284
|
+
def get_includes(query)
|
285
|
+
return [] if query.nil? or !query.has_key?('include') or query['include'].nil?
|
286
|
+
query['include'].split(',')
|
287
|
+
end
|
288
|
+
|
289
|
+
# Get excludes
|
290
|
+
def get_excludes(query)
|
291
|
+
return [] if query.nil? or !query.has_key?('exclude') or query['exclude'].nil?
|
292
|
+
query['exclude'].split(',')
|
293
|
+
end
|
294
|
+
|
295
|
+
# Get sql to load relation
|
296
|
+
def get_relation_query_sql(relation, query)
|
297
|
+
case relation[:type]
|
298
|
+
when :has_one
|
299
|
+
return get_has_one_relation_query_sql(relation, query)
|
300
|
+
when :has_many
|
301
|
+
return get_has_many_relation_query_sql(relation, query)
|
302
|
+
when :has_many_through
|
303
|
+
return get_has_many_through_relation_query_sql(relation, query)
|
304
|
+
else
|
305
|
+
@log.error("Relation type #{relation[:type]} undefined!")
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# Get the SQL query for a has_one relation
|
310
|
+
def get_has_one_relation_query_sql(relation, query)
|
311
|
+
fields = build_select_fields(relation[:table_fields].split(','),'a')
|
312
|
+
|
313
|
+
qry = "SELECT #{fields},`b`.`#{relation[:this_key]}` AS `_table_key` FROM `#{relation[:table]}` AS `a`, `#{@table_name}` AS `b` WHERE (`a`.`#{relation[:table_key]}` = `b`.`#{relation[:this_key]}`)"
|
314
|
+
where = build_where_ns(query,'b')
|
315
|
+
qry += " AND #{where}" unless where.length == 0
|
316
|
+
qry
|
317
|
+
end
|
318
|
+
|
319
|
+
# Get the SQL query for a has_many relation
|
320
|
+
def get_has_many_relation_query_sql(relation, query)
|
321
|
+
fields = build_select_fields(relation[:table_fields].split(','),'a')
|
322
|
+
|
323
|
+
qry = "SELECT #{fields},`b`.`#{relation[:this_key]}` AS `_table_key` FROM `#{relation[:table]}` AS `a`, `#{@table_name}` AS `b` WHERE (`a`.`#{relation[:table_key]}` = `b`.`#{relation[:this_key]}`)"
|
324
|
+
where = build_where_ns(query,'b')
|
325
|
+
qry += " AND #{where}" unless where.length == 0
|
326
|
+
qry
|
327
|
+
end
|
328
|
+
|
329
|
+
# Get the SQL query for a has_many_through relation
|
330
|
+
def get_has_many_through_relation_query_sql(relation,query)
|
331
|
+
fields = build_select_fields(relation[:table_fields].split(','),'a')
|
332
|
+
|
333
|
+
qry = "SELECT #{fields},`c`.`#{relation[:this_key]}` AS `_table_key` FROM `#{relation[:table]}` AS `a`, `#{relation[:link_table]}` AS `b`, `#{@table_name}` AS `c` WHERE (`a`.`#{relation[:table_key]}` = `b`.`#{relation[:link_field]}` AND `b`.`#{relation[:link_key]}` = `c`.`#{relation[:this_key]}`)"
|
334
|
+
where = build_where_ns(query,'c')
|
335
|
+
qry += " AND #{where}" unless where.length == 0
|
336
|
+
qry
|
337
|
+
end
|
338
|
+
|
339
|
+
# Get an array of table names involved in a relation query
|
340
|
+
def get_relation_tables(relation)
|
341
|
+
case relation[:type]
|
342
|
+
when :has_one
|
343
|
+
return [@table_name, relation[:table]].sort
|
344
|
+
when :has_many
|
345
|
+
return [@table_name, relation[:table]].sort
|
346
|
+
when :has_many_through
|
347
|
+
return [@table_name, relation[:table], relation[:link_table]].sort
|
348
|
+
else
|
349
|
+
throw "Unknown Relation type #{relation.type}"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
# Expire a table cache by incrementing the table version
|
354
|
+
def expire_table_cache(table_names)
|
355
|
+
return if @memcache.nil?
|
356
|
+
|
357
|
+
table_names.each do |table_name|
|
358
|
+
key = table_name+"-version"
|
359
|
+
version = @memcache.get(key)
|
360
|
+
if version.nil?
|
361
|
+
@memcache.set(key,1,nil,{:raw=>true})
|
362
|
+
else
|
363
|
+
@memcache.incr(key, 1, nil)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
true
|
368
|
+
end
|
369
|
+
|
370
|
+
# Return true if a key exists
|
371
|
+
def exists_by_primary_key?(primary_key)
|
372
|
+
qry = "SELECT COUNT(*) AS `c` FROM `#{@table_name}` WHERE "+build_where({@primary_key => primary_key})
|
373
|
+
res = cached_query(qry,[@table_name])
|
374
|
+
res[0]['c'] != 0
|
375
|
+
end
|
376
|
+
|
377
|
+
# Return true if an object is valid for create
|
378
|
+
def valid_insert?(data)
|
379
|
+
return false if data.nil?
|
380
|
+
return false if data.keys.length == 0
|
381
|
+
|
382
|
+
# Required fields
|
383
|
+
@fields.each do |k,s|
|
384
|
+
return false if s.has_key?(:required) and s[:required] == true and !data.has_key?(k)
|
385
|
+
end
|
386
|
+
|
387
|
+
# Only valid fields, length checking
|
388
|
+
data.each_key do |k|
|
389
|
+
return false if !@fields.has_key?(k)
|
390
|
+
return false if @fields[k].has_key?(:length) and
|
391
|
+
!data[k].nil? and
|
392
|
+
data[k].length > @fields[k][:length]
|
393
|
+
end
|
394
|
+
|
395
|
+
return true
|
396
|
+
end
|
397
|
+
|
398
|
+
# Return true if an object is valid for update
|
399
|
+
def valid_update?(data)
|
400
|
+
return false if data.nil?
|
401
|
+
return false if data.keys.length == 0
|
402
|
+
|
403
|
+
# Only valid fields, length checking
|
404
|
+
data.each_key do |k|
|
405
|
+
return false if !@fields.has_key?(k)
|
406
|
+
return false if @fields[k].has_key?(:length) and
|
407
|
+
!data[k].nil? and
|
408
|
+
data[k].length > @fields[k][:length]
|
409
|
+
end
|
410
|
+
|
411
|
+
return true
|
412
|
+
end
|
413
|
+
|
414
|
+
# Create a record from data
|
415
|
+
def insert(data)
|
416
|
+
query = "INSERT INTO `#{@table_name}` "+build_insert(data)
|
417
|
+
|
418
|
+
begin
|
419
|
+
queryresult = @mysql.query(query)
|
420
|
+
rescue Exception => e
|
421
|
+
@log.error("#{e}")
|
422
|
+
return false
|
423
|
+
end
|
424
|
+
|
425
|
+
expire_table_cache(get_all_related_tables)
|
426
|
+
|
427
|
+
get_one({@primary_key => data[@primary_key]})
|
428
|
+
end
|
429
|
+
|
430
|
+
# Update a record by its primary key from data
|
431
|
+
def update_by_primary_key(primary_key, data)
|
432
|
+
query = "UPDATE `#{@table_name}` SET "+build_update(data)+" WHERE "+build_where({@primary_key => primary_key})
|
433
|
+
|
434
|
+
begin
|
435
|
+
queryresult = @mysql.query(query)
|
436
|
+
rescue Exception => e
|
437
|
+
@log.error("#{e}")
|
438
|
+
return false
|
439
|
+
end
|
440
|
+
|
441
|
+
expire_table_cache(get_all_related_tables)
|
442
|
+
|
443
|
+
get_one({@primary_key => primary_key})
|
444
|
+
end
|
445
|
+
|
446
|
+
# Delete a record by its primary key from data
|
447
|
+
def delete_by_primary_key(primary_key)
|
448
|
+
query = "DELETE FROM `#{@table_name}` WHERE "+build_where({@primary_key => primary_key})
|
449
|
+
|
450
|
+
begin
|
451
|
+
queryresult = @mysql.query(query)
|
452
|
+
rescue Exception => e
|
453
|
+
@log.error("#{e}")
|
454
|
+
return false
|
455
|
+
end
|
456
|
+
|
457
|
+
expire_table_cache(get_all_related_tables)
|
458
|
+
true
|
459
|
+
end
|
460
|
+
|
461
|
+
# Return an array of all related tables plus this table
|
462
|
+
def get_all_related_tables
|
463
|
+
tables = [ @table_name ]
|
464
|
+
return tables if @relations.nil?
|
465
|
+
@relations.each do |n,r|
|
466
|
+
tables = tables | get_relation_tables(r)
|
467
|
+
end
|
468
|
+
tables.sort
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
data/lib/generic_log.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module CrudService
|
2
|
+
class GenericLog
|
3
|
+
def debug(str)
|
4
|
+
puts "DEBUG: #{str}"
|
5
|
+
end
|
6
|
+
|
7
|
+
def info(str)
|
8
|
+
puts "INFO: #{str}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def warn(str)
|
12
|
+
puts "WARN: #{str}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def error(str)
|
16
|
+
puts "ERROR: #{str}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module CrudService
|
2
|
+
class GenericService
|
3
|
+
|
4
|
+
attr_accessor :dal, :log
|
5
|
+
|
6
|
+
def initialize(dal, log)
|
7
|
+
@dal = dal
|
8
|
+
@log = log
|
9
|
+
end
|
10
|
+
|
11
|
+
# CRUD
|
12
|
+
|
13
|
+
def insert(body)
|
14
|
+
@dal.insert(body)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_all_by_query(query)
|
18
|
+
res = @dal.get_all_by_query(query)
|
19
|
+
@dal.map_in_included_relations!(res,query)
|
20
|
+
res
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_one_by_query(query)
|
24
|
+
res = get_all_by_query(query)
|
25
|
+
return nil if res.length == 0
|
26
|
+
res[0]
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_by_primary_key(primary_key,body)
|
30
|
+
@dal.update_by_primary_key(primary_key,body)
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete_by_primary_key(primary_key)
|
34
|
+
@dal.delete_by_primary_key(primary_key)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Existence
|
38
|
+
|
39
|
+
def exists_by_primary_key?(primary_key)
|
40
|
+
@dal.exists_by_primary_key?(primary_key)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Validation
|
44
|
+
|
45
|
+
def valid_insert?(body)
|
46
|
+
@dal.valid_insert?(body)
|
47
|
+
end
|
48
|
+
|
49
|
+
def valid_query?(query)
|
50
|
+
@dal.valid_query?(query)
|
51
|
+
end
|
52
|
+
|
53
|
+
def valid_update?(body)
|
54
|
+
@dal.valid_update?(body)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crud-service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Cully
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A basic gem for automatic CRUD services using only Sinatra, MySQL and
|
14
|
+
Memcache
|
15
|
+
email: tomhughcully@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/generic_api.rb
|
21
|
+
- lib/generic_dal.rb
|
22
|
+
- lib/generic_log.rb
|
23
|
+
- lib/generic_service.rb
|
24
|
+
homepage: http://rubygems.org/gems/crud-service
|
25
|
+
licenses:
|
26
|
+
- Apache2
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.0.7
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: A Sinatra/MySQL/Memcache CRUD Service Library
|
48
|
+
test_files: []
|