crud-service 0.0.2
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 +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: []
|