fetcheable_on_api 0.1.5 → 0.1.6

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
  SHA256:
3
- metadata.gz: fe1436fc856be39403a098964fd749c327d478b1cd4caa23776b030fa44dbb05
4
- data.tar.gz: 382385b75448f082476ec23adfd4d360b5aa53b8a8cdfb072de4f1dcecf94d63
3
+ metadata.gz: '03812339432d5b98fc4b5c21a591fa89f6d4682e04ffbafca240e24c45bfa9fe'
4
+ data.tar.gz: 4156ce0dd1ab15dfc3c84b28b3caeb6bc45c8aec203ffd9d35b2995a16d78512
5
5
  SHA512:
6
- metadata.gz: 913c31f970e2a6592a0aeab78f4f2e64d37074c120782fff145a7766e1e62a1d6469cf3dc36ec20ff09ff06a98d9978ba035e6a63cebc8beccb71eb96e398e69
7
- data.tar.gz: 9ea51948fc95741f8e751a1371de3f7cdee1ea725751cc814df1b5916ab7c9e09adbc096f84e23ef70e1a20ca3590ec3fa0f75b428a60704ef934ae3d14304b5
6
+ metadata.gz: 4b1e81ab96273f468b159de0fb3bcf366762c63e5743dcb6098b127ed7daa5e63a548f943a1de461022a757a930517f0cacd7dc88bd03e83e90f837393ceb6d5
7
+ data.tar.gz: c41a76a9bd81d7450e3b8c236b375aaa78359474d435f927de89a3a2109723e4570b1d212285a29e06f7f22528cb3eed78b93b99c5ad2ac74c50189dcd8c1d68
data/README.md CHANGED
@@ -46,17 +46,23 @@ class Question < ApplicationRecord
46
46
  foreign_key: 'question_id',
47
47
  dependent: :destroy,
48
48
  inverse_of: :question
49
+
50
+ belongs_to :category,
51
+ class_name: 'Category',
52
+ inverse_of: :questions,
53
+ optional: true
49
54
  end
50
55
 
51
56
  # == Schema Information
52
57
  #
53
58
  # Table name: questions
54
59
  #
55
- # id :bigint(8) not null, primary key
56
- # content :text not null
57
- # position :integer
58
- # created_at :datetime not null
59
- # updated_at :datetime not null
60
+ # id :bigint(8) not null, primary key
61
+ # content :text not null
62
+ # position :integer
63
+ # category_id :bigint(8)
64
+ # created_at :datetime not null
65
+ # updated_at :datetime not null
60
66
  #
61
67
  ```
62
68
 
@@ -88,6 +94,34 @@ end
88
94
  # updated_at :datetime not null
89
95
  #
90
96
  ```
97
+
98
+ ```ruby
99
+ class Category < ApplicationRecord
100
+ #
101
+ # Validations
102
+ #
103
+ validates :name,
104
+ presence: true
105
+
106
+ #
107
+ # Associations
108
+ #
109
+ has_many :questions,
110
+ class_name: 'Question',
111
+ inverse_of: :category
112
+ end
113
+
114
+ # == Schema Information
115
+ #
116
+ # Table name: categories
117
+ #
118
+ # id :bigint(8) not null, primary key
119
+ # name :text not null
120
+ # created_at :datetime not null
121
+ # updated_at :datetime not null
122
+ #
123
+ ```
124
+
91
125
  And controller:
92
126
 
93
127
  ```ruby
@@ -128,18 +162,21 @@ $ curl -X GET \
128
162
  {
129
163
  "id": 3,
130
164
  "position": 1,
165
+ "category_id": 1,
131
166
  "content": "How to simply sort a collection with this gem ?",
132
167
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
133
168
  },
134
169
  {
135
170
  "id": 4,
136
171
  "position": 2,
172
+ "category_id": 2,
137
173
  "content": "Is it so simple?",
138
174
  "answer": "Yes"
139
175
  },
140
176
  {
141
177
  "id": 5,
142
178
  "position": 3,
179
+ "category_id": 2,
143
180
  "content": "Is this real life?",
144
181
  "answer": "Yes this is real life"
145
182
  }
@@ -170,18 +207,21 @@ $ curl -X GET \
170
207
  {
171
208
  "id": 3,
172
209
  "position": 1,
210
+ "category_id": 1,
173
211
  "content": "How to simply sort a collection with this gem ?",
174
212
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
175
213
  },
176
214
  {
177
215
  "id": 4,
178
216
  "position": 2,
217
+ "category_id": 2,
179
218
  "content": "Is it so simple?",
180
219
  "answer": "Yes"
181
220
  },
182
221
  {
183
222
  "id": 5,
184
223
  "position": 3,
224
+ "category_id": 2,
185
225
  "content": "Is this real life?",
186
226
  "answer": "Yes this is real life"
187
227
  }
@@ -198,18 +238,21 @@ $ curl -X GET \
198
238
  {
199
239
  "id": 5,
200
240
  "position": 3,
241
+ "category_id": 2,
201
242
  "content": "Is this real life?",
202
243
  "answer": "Yes this is real life"
203
244
  },
204
245
  {
205
246
  "id": 4,
206
247
  "position": 2,
248
+ "category_id": 2,
207
249
  "content": "Is it so simple?",
208
250
  "answer": "Yes"
209
251
  },
210
252
  {
211
253
  "id": 3,
212
254
  "position": 1,
255
+ "category_id": 1,
213
256
  "content": "How to simply sort a collection with this gem ?",
214
257
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
215
258
  }
@@ -229,12 +272,14 @@ $ curl -X GET \
229
272
  {
230
273
  "id": 3,
231
274
  "position": 1,
275
+ "category_id": 1,
232
276
  "content": "How to simply sort a collection with this gem ?",
233
277
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
234
278
  },
235
279
  {
236
280
  "id": 4,
237
281
  "position": 2,
282
+ "category_id": 2,
238
283
  "content": "Is it so simple?",
239
284
  "answer": "Yes"
240
285
  }
@@ -247,6 +292,7 @@ $ curl -X GET \
247
292
  {
248
293
  "id": 5,
249
294
  "position": 3,
295
+ "category_id": 2,
250
296
  "content": "Is this real life?",
251
297
  "answer": "Yes this is real life"
252
298
  }
@@ -288,6 +334,7 @@ $ curl -X GET \
288
334
  {
289
335
  "id": 3,
290
336
  "position": 1,
337
+ "category_id": 1,
291
338
  "content": "How to simply sort a collection with this gem ?",
292
339
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
293
340
  }
@@ -304,12 +351,14 @@ $ curl -X GET \
304
351
  {
305
352
  "id": 4,
306
353
  "position": 2,
354
+ "category_id": 2,
307
355
  "content": "Is it so simple?",
308
356
  "answer": "Yes"
309
357
  },
310
358
  {
311
359
  "id": 5,
312
360
  "position": 3,
361
+ "category_id": 2,
313
362
  "content": "Is this real life?",
314
363
  "answer": "Yes this is real life"
315
364
  }
@@ -345,12 +394,50 @@ $ curl -X GET \
345
394
  {
346
395
  "id": 3,
347
396
  "position": 1,
397
+ "category_id": 1,
348
398
  "content": "How to simply sort a collection with this gem ?",
349
399
  "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
350
400
  }
351
401
  ]
352
402
  ```
353
403
 
404
+ Furthermore you can specify one of the supported `Arel` predicate.
405
+
406
+ ```ruby
407
+ class QuestionsController < ActionController::Base
408
+ #
409
+ # FetcheableOnApi
410
+ #
411
+ filter_by :category_id, with: :eq
412
+
413
+ # GET /questions
414
+ def index
415
+ questions = apply_fetcheable(Question.includes(:answer).all)
416
+ render json: questions
417
+ end
418
+ end
419
+ ```
420
+
421
+ ```bash
422
+ $ curl -X GET \
423
+ 'http://localhost:3000/questions?filter[category_id]=1'
424
+
425
+ [
426
+ {
427
+ "id": 3,
428
+ "position": 1,
429
+ "category_id": 1,
430
+ "content": "How to simply sort a collection with this gem ?",
431
+ "answer": "Just add sort_by in your controller and call the apply_fetcheable method"
432
+ }
433
+ ]
434
+ ```
435
+
436
+ Currently two kind of predicates are supported:
437
+
438
+ + `:ilike` which is the default behaviour and will match the parameter with the SQL fragment `ILIKE '%foo%'`.
439
+ + `:eq` which matches the parameter with the SQL fragment `= 'foo'`.
440
+
354
441
  And that's all !
355
442
 
356
443
  ## Development
@@ -21,7 +21,7 @@ module FetcheableOnApi
21
21
  def filter_by(*attrs)
22
22
  options = attrs.extract_options!
23
23
  options.symbolize_keys!
24
- options.assert_valid_keys(:as, :class_name)
24
+ options.assert_valid_keys(:as, :class_name, :with)
25
25
 
26
26
  self.filters_configuration = filters_configuration.dup
27
27
 
@@ -45,10 +45,8 @@ module FetcheableOnApi
45
45
  protected
46
46
 
47
47
  def apply_filters(collection)
48
- return collection unless valid_parameters?(params)
49
- return collection unless valid_parameters?(params[:filter])
50
-
51
48
  return collection if params[:filter].blank?
49
+ valid_parameters!(:filter)
52
50
 
53
51
  filter_params = params.require(:filter)
54
52
  .permit(filters_configuration.keys)
@@ -58,8 +56,16 @@ module FetcheableOnApi
58
56
  values.split(',').map do |value|
59
57
  column_name = filters_configuration[column.to_sym].fetch(:as, column)
60
58
  klass = filters_configuration[column.to_sym].fetch(:class_name, collection.klass)
59
+ predicate = filters_configuration[column.to_sym].fetch(:with, :ilike)
61
60
 
62
- klass.arel_table[column_name].matches("%#{value}%")
61
+ case predicate
62
+ when :ilike
63
+ klass.arel_table[column_name].matches("%#{value}%")
64
+ when :eq
65
+ klass.arel_table[column_name].eq(value)
66
+ else
67
+ raise ArgumentError, "unsupported predicate `#{predicate}`"
68
+ end
63
69
  end.inject(:or)
64
70
  end
65
71
 
@@ -20,9 +20,8 @@ module FetcheableOnApi
20
20
  protected
21
21
 
22
22
  def apply_pagination(collection)
23
- return collection unless valid_parameters?(params)
24
- return collection unless valid_parameters?(params[:page])
25
- return collection unless params[:page].present?
23
+ return collection if params[:page].blank?
24
+ valid_parameters!(:page)
26
25
 
27
26
  limit = params[:page].fetch(
28
27
  :size,
@@ -48,10 +48,8 @@ module FetcheableOnApi
48
48
  protected
49
49
 
50
50
  def apply_sort(collection)
51
- return collection unless valid_parameters?(params)
52
- return collection unless valid_parameters?(params[:sort])
53
-
54
51
  return collection if params[:sort].blank?
52
+ valid_parameters!(:sort, permitted_types: [String])
55
53
 
56
54
  ordering = {}
57
55
  sorted_params = params[:sort].split(',')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FetcheableOnApi
4
- VERSION = '0.1.5'.freeze
4
+ VERSION = '0.1.6'.freeze
5
5
  end
@@ -54,9 +54,24 @@ module FetcheableOnApi
54
54
  apply_pagination(collection)
55
55
  end
56
56
 
57
- def valid_parameters?(parameters)
58
- parameters.is_a?(ActionController::Parameters) ||
59
- parameters.is_a?(Hash)
57
+ def valid_parameters!(*keys, permitted_types: default_permitted_types)
58
+ raise ArgumentError.new(
59
+ "Incorrect type #{params.dig(*keys).class} for params #{keys}"
60
+ ) unless valid_params_types(*keys, permitted_types: permitted_types)
61
+ end
62
+
63
+ def valid_params_types(*keys, permitted_types: default_permitted_types)
64
+ permitted_types.inject(false) do |res, type|
65
+ res || valid_params_type(params.dig(*keys), type)
66
+ end
67
+ end
68
+
69
+ def valid_params_type(value, type)
70
+ value.is_a?(type)
71
+ end
72
+
73
+ def default_permitted_types
74
+ [ActionController::Parameters, Hash]
60
75
  end
61
76
  end
62
77
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fetcheable_on_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabien
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-22 00:00:00.000000000 Z
11
+ date: 2018-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport