pureapi 0.3.0 → 0.5.1

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