pureapi 0.3.0 → 0.5.1
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 +4 -4
- data/lib/pureapi.rb +1 -0
- data/lib/pureapi/controller.rb +140 -0
- data/lib/pureapi/model.rb +156 -0
- data/lib/pureapi/postgres_model.rb +75 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1785ebfc9a66dd582d162f50449a27eb66283a97
|
4
|
+
data.tar.gz: 76c8d1f5aaff7c60b576414e41f97a96da52c164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 711367bd3e8cb79b9bd77d015a27a8d87de8bbedea5582c6616a9afee8a600dc13733a5e6d8886626cdc1b9143fcbf39db213a3c5adaa6cf7b4cf4cef69c9723
|
7
|
+
data.tar.gz: 4c3026a51a0ece1227c697d054abcc4cae1bd5eddb5d7be06ad33a336789d40e1ff1f61516464dab68e234ef3474bd33c71c4be6ed2887f28803c553d3c014b9
|
data/lib/pureapi.rb
CHANGED
@@ -3,6 +3,7 @@ module Pureapi
|
|
3
3
|
autoload :Controller, 'pureapi/controller'
|
4
4
|
# autoload :Model, 'pureapi/model'
|
5
5
|
# autoload :MongoidModel, 'pureapi/mongoid_model'
|
6
|
+
# autoload :PostgresModel, 'pureapi/postgres_model'
|
6
7
|
|
7
8
|
# Default way to set up Jwtauth.
|
8
9
|
# a fresh initializer with all configuration values.
|
data/lib/pureapi/controller.rb
CHANGED
@@ -16,6 +16,18 @@ module Pureapi::Controller
|
|
16
16
|
AFTER_REGEX = /\}/
|
17
17
|
|
18
18
|
### Begin 3 main API for GET data
|
19
|
+
# Filter list objects contain search, sort, paginate
|
20
|
+
def core_index_filter(objects)
|
21
|
+
# 1. search
|
22
|
+
objects = default_search_filter(objects)
|
23
|
+
# 2. sort and default sort is id.desc
|
24
|
+
objects = default_sort_filter(objects)
|
25
|
+
# 3. conditions (replace for +default_cond|incond_filter+)
|
26
|
+
objects = core_cond_filter(objects)
|
27
|
+
# 4. paginate
|
28
|
+
objects = paging_standard(objects)
|
29
|
+
end
|
30
|
+
|
19
31
|
# Filter list objects contain search, sort, paginate
|
20
32
|
def default_index_filter(objects)
|
21
33
|
# 1. search
|
@@ -105,6 +117,42 @@ module Pureapi::Controller
|
|
105
117
|
model.as_json(options)
|
106
118
|
end
|
107
119
|
|
120
|
+
# New version of return json for index action
|
121
|
+
def records_as_json(criterias, includes_deep_level = 2)
|
122
|
+
options = {}
|
123
|
+
includes = []
|
124
|
+
|
125
|
+
if params.permit(:fields)[:fields]
|
126
|
+
# Get fields from params
|
127
|
+
_fields = parse_fields(params.permit(:fields)[:fields], includes_deep_level)
|
128
|
+
# Merge with as_json_fields of entity
|
129
|
+
options = merge_as_json(_fields, criterias.as_json_fields)
|
130
|
+
# Get relations for includes
|
131
|
+
includes += include_relations(options)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Reflect options to params
|
135
|
+
params[:fields] = deparse_fields(options)
|
136
|
+
# Get relations for includes from methods
|
137
|
+
includes += criterias.json_method_includes.slice(*options[:methods]).values if !options[:methods].blank?
|
138
|
+
|
139
|
+
criterias.includes(includes).as_json(options)
|
140
|
+
end
|
141
|
+
|
142
|
+
# New version of return json for show action
|
143
|
+
def record_as_json(model, includes_deep_level = 2)
|
144
|
+
options = {}
|
145
|
+
|
146
|
+
if params.permit(:fields)[:fields]
|
147
|
+
# Get fields from params
|
148
|
+
_fields = parse_fields(params.permit(:fields)[:fields], includes_deep_level)
|
149
|
+
# Merge with as_json_fields of entity
|
150
|
+
options = merge_as_json(_fields, model.class.as_json_fields)
|
151
|
+
end
|
152
|
+
|
153
|
+
model.as_json(options)
|
154
|
+
end
|
155
|
+
|
108
156
|
# Define json filters for params in render json api
|
109
157
|
def filter_jsons
|
110
158
|
{
|
@@ -281,6 +329,71 @@ module Pureapi::Controller
|
|
281
329
|
end
|
282
330
|
### End setup of feature comparison conditions
|
283
331
|
|
332
|
+
### Begin setup new version of feature comparison conditions
|
333
|
+
# Filter conditions of object criteria
|
334
|
+
def core_cond_filter(objects)
|
335
|
+
# Default +compcond_params+ for query
|
336
|
+
compcond_params = {}
|
337
|
+
|
338
|
+
# Collaborate params, operators, model to get +compcond_params+
|
339
|
+
if params[:compconds].is_a?(ActionController::Parameters)
|
340
|
+
compcond_params = parse_compcond_fields(params[:compconds], objects)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Assign params[:compconds] after parse
|
344
|
+
params[:compconds] = deparse_compcond_fields(compcond_params)
|
345
|
+
|
346
|
+
# Add conditions of +compcond_params+ to objects
|
347
|
+
objects.compcond_search(compcond_params)
|
348
|
+
end
|
349
|
+
|
350
|
+
def parse_compcond_fields params, model, limit = 10
|
351
|
+
# Default results
|
352
|
+
_results = {only: [], include: {}}
|
353
|
+
|
354
|
+
params.keys.each do |key|
|
355
|
+
# Get field and operator from +key+ of model
|
356
|
+
matchs = model.compcond_match(key)
|
357
|
+
|
358
|
+
if matchs
|
359
|
+
matchs[:v] = params.permit(permit_operator(key, matchs[:o]))[key]
|
360
|
+
|
361
|
+
_results[:only] << matchs
|
362
|
+
end
|
363
|
+
|
364
|
+
# Process for belongs_to relations
|
365
|
+
entity = model.of_entities[key.to_sym]
|
366
|
+
|
367
|
+
if limit > 1 && entity && params[key].is_a?(ActionController::Parameters)
|
368
|
+
_results[:include][key.to_sym] = parse_compcond_fields(params[key], entity, limit - 1)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
_results
|
373
|
+
end
|
374
|
+
|
375
|
+
def deparse_compcond_fields compcond_params
|
376
|
+
# Default results
|
377
|
+
_results = {}
|
378
|
+
|
379
|
+
# Assign from +compcond_params[:only]+
|
380
|
+
compcond_params[:only] && compcond_params[:only].each do |item|
|
381
|
+
_results["#{item[:f]}.#{item[:o]}"] = item[:v]
|
382
|
+
end
|
383
|
+
|
384
|
+
# Assign from +compcond_params[:include]+
|
385
|
+
compcond_params[:include] && compcond_params[:include].each do |key, item|
|
386
|
+
_results[key] = deparse_compcond_fields(item)
|
387
|
+
end
|
388
|
+
|
389
|
+
_results
|
390
|
+
end
|
391
|
+
|
392
|
+
def permit_operator key, operator
|
393
|
+
Pureapi::Model::PERMIT_OPERATORS[operator] ? { key => Pureapi::Model::PERMIT_OPERATORS[operator] } : key
|
394
|
+
end
|
395
|
+
### End setup new version of feature comparison conditions
|
396
|
+
|
284
397
|
### Begin setup of paging_standard. If not use will_paginate, write in mode class
|
285
398
|
# Method validate page number (like page params)
|
286
399
|
def validate_page(page, page_total)
|
@@ -312,6 +425,33 @@ module Pureapi::Controller
|
|
312
425
|
### End setup of paging_standard
|
313
426
|
|
314
427
|
### Begin feature records_json and record_json which render format json
|
428
|
+
# Merge target from request params, source from model
|
429
|
+
#
|
430
|
+
# Arguments:
|
431
|
+
# target: (Hash)
|
432
|
+
# source: (Hash)
|
433
|
+
def merge_as_json(target ,source)
|
434
|
+
result = {}
|
435
|
+
|
436
|
+
if source[:only].is_a?(Array)
|
437
|
+
result[:only] = target[:only].is_a?(Array) ? (target[:only] & source[:only]) : source[:only]
|
438
|
+
end
|
439
|
+
|
440
|
+
if source[:methods].is_a?(Array) && target[:only].is_a?(Array)
|
441
|
+
result[:methods] = target[:only] & source[:methods]
|
442
|
+
end
|
443
|
+
|
444
|
+
if source[:include].is_a?(Hash) && target[:include].is_a?(Hash)
|
445
|
+
result[:include] = {}
|
446
|
+
|
447
|
+
(source[:include].keys & target[:include].keys).each do |k|
|
448
|
+
result[:include][k] = merge_as_json(target[:include][k], source[:include][k])
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
result.delete_if { |k, v| v.blank? }
|
453
|
+
end
|
454
|
+
|
315
455
|
# Methods return hash contain full params use for ActiveRecord includes()
|
316
456
|
# and ActiveModel::Serializers::JSON as_json()
|
317
457
|
def parse_includes(fields, model, includes_deep_level = 2)
|
data/lib/pureapi/model.rb
CHANGED
@@ -33,6 +33,33 @@ module Pureapi::Model
|
|
33
33
|
LOGICAL_OPERATORS_INVERT = LOGICAL_OPERATORS.invert
|
34
34
|
NULL_OPERATOR_KEYS = NULL_OPERATORS.keys
|
35
35
|
|
36
|
+
# New version of +COMPARISON_OPERATORS+ & others
|
37
|
+
module Operators
|
38
|
+
EQ = { id: :eq, is: '=' }
|
39
|
+
NE = { id: :ne, is: '<>' }
|
40
|
+
GT = { id: :gt, is: '>' }
|
41
|
+
LT = { id: :lt, is: '<' }
|
42
|
+
GTE = { id: :gte, is: '>=' }
|
43
|
+
LTE = { id: :lte, is: '<=' }
|
44
|
+
LIKE = { id: :like, is: 'LIKE' }
|
45
|
+
NLIKE = { id: :nlike, is: 'NOT LIKE' }
|
46
|
+
REGEXP = { id: :regexp, is: 'REGEXP' }
|
47
|
+
IN = { id: :in, is: 'IN', permit: [] }
|
48
|
+
ISNIL = { id: :isnil, is: 'IS NULL' }
|
49
|
+
ISNNIL = { id: :isnnil, is: 'IS NOT NULL' }
|
50
|
+
end
|
51
|
+
|
52
|
+
REFLECT_OPERATORS = Operators.constants.inject({}) do |memo, const_name|
|
53
|
+
item = Operators.const_get(const_name)
|
54
|
+
memo[item[:id]] = item[:is]
|
55
|
+
memo
|
56
|
+
end
|
57
|
+
|
58
|
+
PERMIT_OPERATORS = Operators.constants.inject({}) do |memo, const_name|
|
59
|
+
item = Operators.const_get(const_name)
|
60
|
+
memo[item[:id]] = item[:permit]
|
61
|
+
memo
|
62
|
+
end
|
36
63
|
|
37
64
|
# return default array contains methods for as_json
|
38
65
|
# Eg. [:status_name, :path_detail, :restrictions, :channel_course_code]
|
@@ -158,8 +185,137 @@ module Pureapi::Model
|
|
158
185
|
self.column_names.map(&:to_sym)
|
159
186
|
end
|
160
187
|
|
188
|
+
# Define relation entities can be included
|
189
|
+
# Example:
|
190
|
+
# >> {User => [:manager], Department => [:department]}
|
191
|
+
def include_entities
|
192
|
+
{}
|
193
|
+
end
|
194
|
+
|
161
195
|
# Require params is hash contain Integer :page, :per_page
|
162
196
|
def paginate(params)
|
163
197
|
self.limit(params[:per_page]).offset((params[:page] - 1) * params[:per_page])
|
164
198
|
end
|
199
|
+
|
200
|
+
# Get all includes of relations in model
|
201
|
+
def get_includes nested_entities
|
202
|
+
_results = {}
|
203
|
+
_entities = include_entities
|
204
|
+
|
205
|
+
(_entities.keys - nested_entities).each do |_c|
|
206
|
+
_entities[_c].each do |_r|
|
207
|
+
_results[_r] = _c._json_fields(nested_entities)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
_results
|
212
|
+
end
|
213
|
+
|
214
|
+
# Return all available values around model
|
215
|
+
def _json_fields nested_entities = []
|
216
|
+
nested_entities << self
|
217
|
+
|
218
|
+
{
|
219
|
+
only: default_onlyasjsons,
|
220
|
+
methods: json_methods,
|
221
|
+
include: get_includes(nested_entities),
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
# Static of +_json_fields+
|
226
|
+
def as_json_fields
|
227
|
+
@as_json_fields ||= self._json_fields
|
228
|
+
end
|
229
|
+
|
230
|
+
### Begin methods for feature compconds filter
|
231
|
+
# Return list of all belongs_to => class_name
|
232
|
+
# Example:
|
233
|
+
# >> {ad: Ad, lead_level: LeadLevel, course: Course}
|
234
|
+
def of_entities
|
235
|
+
{}
|
236
|
+
end
|
237
|
+
|
238
|
+
# Full compcond regexp for key
|
239
|
+
# Example:
|
240
|
+
# >> id.gte
|
241
|
+
def compcond_regexp
|
242
|
+
@compcond_regexp ||= /^(#{compcond_columns.join("|")})\.(#{REFLECT_OPERATORS.keys.join("|")})$/
|
243
|
+
end
|
244
|
+
|
245
|
+
# Compcond regexp for key
|
246
|
+
# Example:
|
247
|
+
# >> id
|
248
|
+
def compcond_regexp2nd
|
249
|
+
@compcond_regexp2nd ||= /^(#{compcond_columns.join("|")})$/
|
250
|
+
end
|
251
|
+
|
252
|
+
# Return matchs of key with +compcond_regexp+ || +compcond_regexp2nd+
|
253
|
+
def compcond_match(str)
|
254
|
+
_matchs = compcond_regexp.match(str) || compcond_regexp2nd.match(str)
|
255
|
+
|
256
|
+
if _matchs
|
257
|
+
{
|
258
|
+
f: _matchs[1],
|
259
|
+
o: _matchs[2] ? _matchs[2].to_sym : :eq,
|
260
|
+
}
|
261
|
+
else
|
262
|
+
nil
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return all fields can use for search of model
|
267
|
+
def _search_fields
|
268
|
+
_results = {only: compcond_columns, include: {}}
|
269
|
+
|
270
|
+
of_entities.each do |entity, _c|
|
271
|
+
_results[:include][entity] = _c._search_fields
|
272
|
+
end
|
273
|
+
|
274
|
+
_results
|
275
|
+
end
|
276
|
+
|
277
|
+
# Static of +_search_fields+
|
278
|
+
def compcond_fields
|
279
|
+
@compcond_fields ||= self._search_fields
|
280
|
+
end
|
281
|
+
|
282
|
+
# Search by params of attributes of model
|
283
|
+
def _self_search only_params
|
284
|
+
criterias = self
|
285
|
+
|
286
|
+
only_params.each do |filter|
|
287
|
+
case filter[:o]
|
288
|
+
when Operators::EQ[:id], Operators::IN[:id]
|
289
|
+
criterias = criterias.where(filter[:f] => filter[:v])
|
290
|
+
when Operators::ISNIL[:id], Operators::ISNNIL[:id]
|
291
|
+
criterias = criterias.where("`#{self.table_name}`.`#{filter[:f]}` #{REFLECT_OPERATORS[filter[:o]]}")
|
292
|
+
else
|
293
|
+
criterias = criterias.where("`#{self.table_name}`.`#{filter[:f]}` #{REFLECT_OPERATORS[filter[:o]]} ?", filter[:v])
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
return criterias.where({})
|
298
|
+
end
|
299
|
+
|
300
|
+
# Search by params of relations
|
301
|
+
def _include_search include_params
|
302
|
+
criterias = self
|
303
|
+
|
304
|
+
include_params.each do |entity, query|
|
305
|
+
criterias = criterias.where(entity => of_entities[entity].compcond_search(query)) if of_entities[entity]
|
306
|
+
end
|
307
|
+
|
308
|
+
return criterias.where({})
|
309
|
+
end
|
310
|
+
|
311
|
+
# Collaborate +_self_search+ & +_include_search+
|
312
|
+
def compcond_search params
|
313
|
+
criterias = self
|
314
|
+
|
315
|
+
criterias = criterias._self_search(params[:only]) if params[:only].is_a?(Array)
|
316
|
+
criterias = criterias._include_search(params[:include]) if params[:include].is_a?(Hash)
|
317
|
+
|
318
|
+
return criterias.where({})
|
319
|
+
end
|
320
|
+
### End methods for feature compconds filter
|
165
321
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'pureapi/model'
|
3
|
+
|
4
|
+
# Provide methods (override, polymorphic) for use data handling
|
5
|
+
# # => comfortable when use postgresql
|
6
|
+
|
7
|
+
module Pureapi::PostgresModel
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
include Pureapi::Model
|
10
|
+
|
11
|
+
# New version of +COMPARISON_OPERATORS+ & others
|
12
|
+
module Operators
|
13
|
+
EQ = { id: :eq, is: '=' }
|
14
|
+
NE = { id: :ne, is: '<>' }
|
15
|
+
GT = { id: :gt, is: '>' }
|
16
|
+
LT = { id: :lt, is: '<' }
|
17
|
+
GTE = { id: :gte, is: '>=' }
|
18
|
+
LTE = { id: :lte, is: '<=' }
|
19
|
+
LIKE = { id: :like, is: 'LIKE' }
|
20
|
+
NLIKE = { id: :nlike, is: 'NOT LIKE' }
|
21
|
+
REGEXP = { id: :regexp, is: '~' }
|
22
|
+
IN = { id: :in, is: 'IN', permit: [] }
|
23
|
+
ISNIL = { id: :isnil, is: 'IS NULL' }
|
24
|
+
ISNNIL = { id: :isnnil, is: 'IS NOT NULL' }
|
25
|
+
end
|
26
|
+
|
27
|
+
REFLECT_OPERATORS = Operators.constants.inject({}) do |memo, const_name|
|
28
|
+
item = Operators.const_get(const_name)
|
29
|
+
memo[item[:id]] = item[:is]
|
30
|
+
memo
|
31
|
+
end
|
32
|
+
|
33
|
+
PERMIT_OPERATORS = Operators.constants.inject({}) do |memo, const_name|
|
34
|
+
item = Operators.const_get(const_name)
|
35
|
+
memo[item[:id]] = item[:permit]
|
36
|
+
memo
|
37
|
+
end
|
38
|
+
|
39
|
+
# Comparsion operator conditions method
|
40
|
+
# Array +params+ contains hash = {f, o, v}
|
41
|
+
# :f is column name
|
42
|
+
# :o is comparsion operator
|
43
|
+
# :v is value
|
44
|
+
def compconds(params = [])
|
45
|
+
criterias = self
|
46
|
+
|
47
|
+
params.each do |param|
|
48
|
+
if param[:o] == COMPARISON_OPERATORS[:eq]
|
49
|
+
criterias = criterias.where(param[:f] => param[:v])
|
50
|
+
else
|
51
|
+
criterias = criterias.where("\"#{self.table_name}\".\"#{param[:f]}\" #{param[:o]} ?", param[:v])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
return criterias.where({})
|
56
|
+
end
|
57
|
+
|
58
|
+
# Search by params of attributes of model
|
59
|
+
def _self_search only_params
|
60
|
+
criterias = self
|
61
|
+
|
62
|
+
only_params.each do |filter|
|
63
|
+
case filter[:o]
|
64
|
+
when Operators::EQ[:id], Operators::IN[:id]
|
65
|
+
criterias = criterias.where(filter[:f] => filter[:v])
|
66
|
+
when Operators::ISNIL[:id], Operators::ISNNIL[:id]
|
67
|
+
criterias = criterias.where("\"#{self.table_name}\".\"#{filter[:f]}\" #{REFLECT_OPERATORS[filter[:o]]}")
|
68
|
+
else
|
69
|
+
criterias = criterias.where("\"#{self.table_name}\".\"#{filter[:f]}\" #{REFLECT_OPERATORS[filter[:o]]} ?", filter[:v])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
return criterias.where({})
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pureapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dieu Pham
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- lib/pureapi/controller.rb
|
37
37
|
- lib/pureapi/model.rb
|
38
38
|
- lib/pureapi/mongoid_model.rb
|
39
|
+
- lib/pureapi/postgres_model.rb
|
39
40
|
homepage: http://rubygems.org/gems/pureapi
|
40
41
|
licenses:
|
41
42
|
- MIT
|