fetcheable_on_api 0.1.5 → 0.1.6

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
  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