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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04513fc90902a3fe0fb33d34312b7d73a741333f
4
- data.tar.gz: c50754ff88d2863babdb95dafa6109369addeadc
3
+ metadata.gz: 1785ebfc9a66dd582d162f50449a27eb66283a97
4
+ data.tar.gz: 76c8d1f5aaff7c60b576414e41f97a96da52c164
5
5
  SHA512:
6
- metadata.gz: c7915efdc3dee1f11e9afc7ab2803ad1d581d70f44eb7cfb66ebeb2bd90fd9af4792b9a9459858900860030382d902b66e1fa23b7e09f929337601a750bf01ae
7
- data.tar.gz: 4022dc3fa66e213c9a01c31dfc5ed13ce043ceb5c018eace3f4126bd0d7b356c5d2e50e20d27bea32e94e37430f3469745d925daccb80f439c75109bacca0335
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.
@@ -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.3.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