actionset 0.8.2 → 0.9.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +24 -0
  3. data/Gemfile.lock +1 -1
  4. data/Rakefile +7 -1
  5. data/actionset.gemspec +1 -1
  6. data/lib/action_set.rb +36 -7
  7. data/lib/action_set/attribute_value.rb +7 -1
  8. data/lib/action_set/helpers/helper_methods.rb +2 -1
  9. data/lib/action_set/helpers/pagination/record_description_for_helper.rb +20 -0
  10. data/lib/action_set/helpers/pagination/record_first_for_helper.rb +20 -0
  11. data/lib/action_set/helpers/pagination/record_last_for_helper.rb +26 -0
  12. data/lib/action_set/helpers/pagination/record_range_for_helper.rb +25 -0
  13. data/lib/action_set/helpers/pagination/record_size_for_helper.rb +9 -0
  14. data/lib/action_set/helpers/pagination/total_pages_for_helper.rb +3 -1
  15. data/lib/active_set/active_record_set_instruction.rb +30 -37
  16. data/lib/active_set/attribute_instruction.rb +2 -2
  17. data/lib/active_set/enumerable_set_instruction.rb +13 -26
  18. data/lib/active_set/filtering/active_record/operators.rb +277 -0
  19. data/lib/active_set/filtering/active_record/query_column.rb +35 -0
  20. data/lib/active_set/filtering/active_record/query_value.rb +47 -0
  21. data/lib/active_set/filtering/active_record/set_instruction.rb +29 -0
  22. data/lib/active_set/filtering/active_record/strategy.rb +87 -0
  23. data/lib/active_set/filtering/constants.rb +349 -0
  24. data/lib/active_set/filtering/enumerable/operators.rb +308 -0
  25. data/lib/active_set/filtering/enumerable/set_instruction.rb +98 -0
  26. data/lib/active_set/filtering/enumerable/strategy.rb +90 -0
  27. data/lib/active_set/filtering/operation.rb +4 -4
  28. data/lib/helpers/flatten_keys_of.rb +1 -1
  29. metadata +16 -4
  30. data/lib/active_set/filtering/active_record_strategy.rb +0 -85
  31. data/lib/active_set/filtering/enumerable_strategy.rb +0 -79
@@ -0,0 +1,349 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveSet
4
+ module Filtering
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module Constants
7
+ BLANK_VALUES = [nil, ''].freeze
8
+
9
+ PREDICATES = {
10
+ EQ: {
11
+ type: :binary,
12
+ compound: false,
13
+ behavior: :inclusive,
14
+ shorthand: :'=='
15
+ },
16
+ NOT_EQ: {
17
+ type: :binary,
18
+ compound: false,
19
+ behavior: :exclusive,
20
+ shorthand: :'!='
21
+ },
22
+ EQ_ANY: {
23
+ type: :binary,
24
+ compound: true,
25
+ behavior: :inclusive,
26
+ shorthand: :'E=='
27
+ },
28
+ EQ_ALL: {
29
+ type: :binary,
30
+ compound: true,
31
+ behavior: :exclusive,
32
+ shorthand: :'A=='
33
+ },
34
+ NOT_EQ_ANY: {
35
+ type: :binary,
36
+ compound: true,
37
+ behavior: :inclusive,
38
+ shorthand: :'E!='
39
+ },
40
+ NOT_EQ_ALL: {
41
+ type: :binary,
42
+ compound: true,
43
+ behavior: :exclusive,
44
+ shorthand: :'A!='
45
+ },
46
+
47
+ IN: {
48
+ type: :binary,
49
+ compound: true,
50
+ behavior: :inclusive,
51
+ shorthand: :'<<'
52
+ },
53
+ NOT_IN: {
54
+ type: :binary,
55
+ compound: true,
56
+ behavior: :exclusive,
57
+ shorthand: :'!<'
58
+ },
59
+ IN_ANY: {
60
+ type: :binary,
61
+ compound: true,
62
+ behavior: :inclusive,
63
+ shorthand: :'E<<'
64
+ },
65
+ IN_ALL: {
66
+ type: :binary,
67
+ compound: true,
68
+ behavior: :exclusive,
69
+ shorthand: :'A<<'
70
+ },
71
+ NOT_IN_ANY: {
72
+ type: :binary,
73
+ compound: true,
74
+ behavior: :inclusive,
75
+ shorthand: :'E!<'
76
+ },
77
+ NOT_IN_ALL: {
78
+ type: :binary,
79
+ compound: true,
80
+ behavior: :exclusive,
81
+ shorthand: :'A!<'
82
+ },
83
+
84
+ MATCHES: {
85
+ type: :binary,
86
+ compound: false,
87
+ behavior: :inclusive,
88
+ shorthand: :'=~'
89
+ },
90
+ DOES_NOT_MATCH: {
91
+ type: :binary,
92
+ compound: false,
93
+ behavior: :exclusive,
94
+ shorthand: :'!~'
95
+ },
96
+ MATCHES_ANY: {
97
+ type: :binary,
98
+ compound: true,
99
+ behavior: :inclusive,
100
+ shorthand: :'E=~'
101
+ },
102
+ MATCHES_ALL: {
103
+ type: :binary,
104
+ compound: true,
105
+ behavior: :exclusive,
106
+ shorthand: :'A=~'
107
+ },
108
+ DOES_NOT_MATCH_ANY: {
109
+ type: :binary,
110
+ compound: true,
111
+ behavior: :inclusive,
112
+ shorthand: :'E!~'
113
+ },
114
+ DOES_NOT_MATCH_ALL: {
115
+ type: :binary,
116
+ compound: true,
117
+ behavior: :exclusive,
118
+ shorthand: :'A!~'
119
+ },
120
+
121
+ LT: {
122
+ type: :binary,
123
+ compound: false,
124
+ behavior: :exclusive,
125
+ shorthand: :'<'
126
+ },
127
+ LTEQ: {
128
+ type: :binary,
129
+ compound: false,
130
+ behavior: :inclusive,
131
+ shorthand: :'<='
132
+ },
133
+ LT_ANY: {
134
+ type: :binary,
135
+ compound: true,
136
+ behavior: :inconclusive,
137
+ shorthand: :'E<'
138
+ },
139
+ LT_ALL: {
140
+ type: :binary,
141
+ compound: true,
142
+ behavior: :exclusive,
143
+ shorthand: :'A<'
144
+ },
145
+ LTEQ_ANY: {
146
+ type: :binary,
147
+ compound: true,
148
+ behavior: :inclusive,
149
+ shorthand: :'E<='
150
+ },
151
+ LTEQ_ALL: {
152
+ type: :binary,
153
+ compound: true,
154
+ behavior: :inconclusive,
155
+ shorthand: :'A<='
156
+ },
157
+
158
+ GT: {
159
+ type: :binary,
160
+ compound: false,
161
+ behavior: :exclusive,
162
+ shorthand: :'>'
163
+ },
164
+ GTEQ: {
165
+ type: :binary,
166
+ compound: false,
167
+ behavior: :inclusive,
168
+ shorthand: :'>='
169
+ },
170
+ GT_ANY: {
171
+ type: :binary,
172
+ compound: true,
173
+ behavior: :inconclusive,
174
+ shorthand: :'E>'
175
+ },
176
+ GT_ALL: {
177
+ type: :binary,
178
+ compound: true,
179
+ behavior: :exclusive,
180
+ shorthand: :'A>'
181
+ },
182
+ GTEQ_ANY: {
183
+ type: :binary,
184
+ compound: true,
185
+ behavior: :inclusive,
186
+ shorthand: :'E>='
187
+ },
188
+ GTEQ_ALL: {
189
+ type: :binary,
190
+ compound: true,
191
+ behavior: :inconclusive,
192
+ shorthand: :'A>='
193
+ },
194
+
195
+ BETWEEN: {
196
+ type: :binary,
197
+ compound: true,
198
+ behavior: :inclusive,
199
+ shorthand: :'..'
200
+ },
201
+ NOT_BETWEEN: {
202
+ type: :binary,
203
+ compound: true,
204
+ behavior: :exclusive,
205
+ shorthand: :'!.'
206
+ },
207
+
208
+ IS_TRUE: {
209
+ type: :unary,
210
+ operator: :eq,
211
+ compound: false,
212
+ behavior: :inconclusive
213
+ },
214
+ IS_FALSE: {
215
+ type: :unary,
216
+ operator: :eq,
217
+ compound: false,
218
+ behavior: :inconclusive
219
+ },
220
+
221
+ IS_NULL: {
222
+ type: :unary,
223
+ operator: :eq,
224
+ compound: false,
225
+ behavior: :exclusive,
226
+ query_attribute_transformer: proc { |_| nil }
227
+ },
228
+ NOT_NULL: {
229
+ type: :unary,
230
+ operator: :not_eq,
231
+ compound: false,
232
+ behavior: :inclusive,
233
+ query_attribute_transformer: proc { |_| nil }
234
+ },
235
+
236
+ IS_PRESENT: {
237
+ type: :unary,
238
+ operator: :not_eq_all,
239
+ compound: false,
240
+ behavior: :inclusive
241
+ },
242
+ IS_BLANK: {
243
+ type: :unary,
244
+ operator: :eq_any,
245
+ compound: false,
246
+ behavior: :exclusive
247
+ },
248
+
249
+ MATCH_START: {
250
+ type: :binary,
251
+ compound: false,
252
+ behavior: :inclusive
253
+ },
254
+ MATCH_START_ANY: {
255
+ type: :binary,
256
+ compound: true,
257
+ behavior: :inclusive
258
+ },
259
+ MATCH_START_ALL: {
260
+ type: :binary,
261
+ compound: true,
262
+ behavior: :exclusive
263
+ },
264
+ MATCH_NOT_START: {
265
+ type: :binary,
266
+ compound: false,
267
+ behavior: :exclusive
268
+ },
269
+ MATCH_NOT_START_ANY: {
270
+ type: :binary,
271
+ compound: true,
272
+ behavior: :inclusive
273
+ },
274
+ MATCH_NOT_START_ALL: {
275
+ type: :binary,
276
+ compound: true,
277
+ behavior: :exclusive
278
+ },
279
+ MATCH_END: {
280
+ type: :binary,
281
+ compound: false,
282
+ behavior: :inclusive
283
+ },
284
+ MATCH_END_ANY: {
285
+ type: :binary,
286
+ compound: true,
287
+ behavior: :inclusive
288
+ },
289
+ MATCH_END_ALL: {
290
+ type: :binary,
291
+ compound: true,
292
+ behavior: :exclusive
293
+ },
294
+ MATCH_NOT_END: {
295
+ type: :binary,
296
+ compound: false,
297
+ behavior: :exclusive
298
+ },
299
+ MATCH_NOT_END_ANY: {
300
+ type: :binary,
301
+ compound: true,
302
+ behavior: :inclusive
303
+ },
304
+ MATCH_NOT_END_ALL: {
305
+ type: :binary,
306
+ compound: true,
307
+ behavior: :exclusive
308
+ },
309
+ MATCH_CONTAIN: {
310
+ type: :binary,
311
+ compound: false,
312
+ behavior: :inclusive,
313
+ shorthand: :'~*'
314
+ },
315
+ MATCH_CONTAIN_ANY: {
316
+ type: :binary,
317
+ compound: true,
318
+ behavior: :inclusive,
319
+ shorthand: :'E~*'
320
+ },
321
+ MATCH_CONTAIN_ALL: {
322
+ type: :binary,
323
+ compound: true,
324
+ behavior: :exclusive,
325
+ shorthand: :'A~*'
326
+ },
327
+ MATCH_NOT_CONTAIN: {
328
+ type: :binary,
329
+ compound: false,
330
+ behavior: :exclusive,
331
+ shorthand: :'!*'
332
+ },
333
+ MATCH_NOT_CONTAIN_ANY: {
334
+ type: :binary,
335
+ compound: true,
336
+ behavior: :inclusive,
337
+ shorthand: :'E!*'
338
+ },
339
+ MATCH_NOT_CONTAIN_ALL: {
340
+ type: :binary,
341
+ compound: true,
342
+ behavior: :exclusive,
343
+ shorthand: :'A!*'
344
+ }
345
+ }.freeze
346
+ end
347
+ # rubocop:enable Metrics/ModuleLength
348
+ end
349
+ end
@@ -0,0 +1,308 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../constants'
4
+
5
+ class ActiveSet
6
+ module Filtering
7
+ module Enumerable
8
+ # rubocop:disable Metrics/ModuleLength
9
+ module Operators
10
+ NOT_TRANSFORMER = ->(result) { !result }
11
+ RANGE_TRANSFORMER = ->(value) { Range.new(*value.sort) }
12
+ REGEXP_TRANSFORMER = ->(value) { /#{Regexp.quote(value.to_s)}/ }
13
+ STRING_TRANSFORMER = ->(value) { value.to_s }
14
+
15
+ PREDICATES = {
16
+ EQ: {
17
+ operator: :'=='
18
+ },
19
+ NOT_EQ: {
20
+ operator: :'!='
21
+ },
22
+ EQ_ANY: {
23
+ operator: :'==',
24
+ reducer: :any?
25
+ },
26
+ EQ_ALL: {
27
+ operator: :'==',
28
+ reducer: :all?
29
+ },
30
+ NOT_EQ_ANY: {
31
+ operator: :'!=',
32
+ reducer: :any?
33
+ },
34
+ NOT_EQ_ALL: {
35
+ operator: :'!=',
36
+ reducer: :all?
37
+ },
38
+
39
+ IN: {
40
+ operator: :presence_in
41
+ },
42
+ NOT_IN: {
43
+ operator: :presence_in,
44
+ result_transformer: NOT_TRANSFORMER
45
+ },
46
+ IN_ANY: {
47
+ operator: :presence_in,
48
+ reducer: :any?
49
+ },
50
+ IN_ALL: {
51
+ operator: :presence_in,
52
+ reducer: :all?
53
+ },
54
+ NOT_IN_ANY: {
55
+ operator: :presence_in,
56
+ reducer: :any?,
57
+ result_transformer: NOT_TRANSFORMER
58
+ },
59
+ NOT_IN_ALL: {
60
+ operator: :presence_in,
61
+ reducer: :all?,
62
+ result_transformer: NOT_TRANSFORMER
63
+ },
64
+
65
+ MATCHES: {
66
+ operator: :'=~',
67
+ object_attribute_transformer: STRING_TRANSFORMER,
68
+ query_attribute_transformer: REGEXP_TRANSFORMER
69
+ },
70
+ DOES_NOT_MATCH: {
71
+ operator: :'!~',
72
+ object_attribute_transformer: STRING_TRANSFORMER,
73
+ query_attribute_transformer: REGEXP_TRANSFORMER
74
+ },
75
+ MATCHES_ANY: {
76
+ operator: :'=~',
77
+ reducer: :any?,
78
+ object_attribute_transformer: STRING_TRANSFORMER,
79
+ query_attribute_transformer: REGEXP_TRANSFORMER
80
+ },
81
+ MATCHES_ALL: {
82
+ operator: :'=~',
83
+ reducer: :all?,
84
+ object_attribute_transformer: STRING_TRANSFORMER,
85
+ query_attribute_transformer: REGEXP_TRANSFORMER
86
+ },
87
+ DOES_NOT_MATCH_ANY: {
88
+ operator: :'!~',
89
+ reducer: :any?,
90
+ object_attribute_transformer: STRING_TRANSFORMER,
91
+ query_attribute_transformer: REGEXP_TRANSFORMER
92
+ },
93
+ DOES_NOT_MATCH_ALL: {
94
+ operator: :'!~',
95
+ reducer: :all?,
96
+ object_attribute_transformer: STRING_TRANSFORMER,
97
+ query_attribute_transformer: REGEXP_TRANSFORMER
98
+ },
99
+
100
+ LT: {
101
+ operator: :'<'
102
+ },
103
+ LTEQ: {
104
+ operator: :'<='
105
+ },
106
+ LT_ANY: {
107
+ operator: :'<',
108
+ reducer: :any?
109
+ },
110
+ LT_ALL: {
111
+ operator: :'<',
112
+ reducer: :all?
113
+ },
114
+ LTEQ_ANY: {
115
+ operator: :'<=',
116
+ reducer: :any?
117
+ },
118
+ LTEQ_ALL: {
119
+ operator: :'<=',
120
+ reducer: :all?
121
+ },
122
+
123
+ GT: {
124
+ operator: :'>'
125
+ },
126
+ GTEQ: {
127
+ operator: :'>='
128
+ },
129
+ GT_ANY: {
130
+ operator: :'>',
131
+ reducer: :any?
132
+ },
133
+ GT_ALL: {
134
+ operator: :'>',
135
+ reducer: :all?
136
+ },
137
+ GTEQ_ANY: {
138
+ operator: :'>=',
139
+ reducer: :any?
140
+ },
141
+ GTEQ_ALL: {
142
+ operator: :'>=',
143
+ reducer: :all?
144
+ },
145
+
146
+ BETWEEN: {
147
+ operator: :cover?,
148
+ query_attribute_transformer: RANGE_TRANSFORMER
149
+ },
150
+ NOT_BETWEEN: {
151
+ operator: :cover?,
152
+ query_attribute_transformer: RANGE_TRANSFORMER,
153
+ result_transformer: NOT_TRANSFORMER
154
+ },
155
+
156
+ IS_TRUE: {
157
+ operator: :'==',
158
+ query_attribute_transformer: proc { |_| 1 }
159
+ },
160
+ IS_FALSE: {
161
+ operator: :'==',
162
+ query_attribute_transformer: proc { |_| 0 }
163
+ },
164
+
165
+ IS_NULL: {
166
+ operator: :'=='
167
+ },
168
+ NOT_NULL: {
169
+ operator: :'!='
170
+ },
171
+
172
+ IS_PRESENT: {
173
+ operator: :'!=',
174
+ reducer: :all?,
175
+ query_attribute_transformer: proc { |_| Constants::BLANK_VALUES }
176
+ },
177
+ IS_BLANK: {
178
+ operator: :'==',
179
+ reducer: :any?,
180
+ query_attribute_transformer: proc { |_| Constants::BLANK_VALUES }
181
+ },
182
+
183
+ MATCH_START: {
184
+ operator: :'start_with?',
185
+ object_attribute_transformer: STRING_TRANSFORMER,
186
+ query_attribute_transformer: STRING_TRANSFORMER
187
+ },
188
+ MATCH_START_ANY: {
189
+ operator: :'start_with?',
190
+ reducer: :any?,
191
+ object_attribute_transformer: STRING_TRANSFORMER,
192
+ query_attribute_transformer: STRING_TRANSFORMER
193
+ },
194
+ MATCH_START_ALL: {
195
+ operator: :'start_with?',
196
+ reducer: :all?,
197
+ object_attribute_transformer: STRING_TRANSFORMER,
198
+ query_attribute_transformer: STRING_TRANSFORMER
199
+ },
200
+ MATCH_NOT_START: {
201
+ operator: :'start_with?',
202
+ object_attribute_transformer: STRING_TRANSFORMER,
203
+ query_attribute_transformer: STRING_TRANSFORMER,
204
+ result_transformer: NOT_TRANSFORMER
205
+ },
206
+ MATCH_NOT_START_ANY: {
207
+ operator: :'start_with?',
208
+ reducer: :any?,
209
+ object_attribute_transformer: STRING_TRANSFORMER,
210
+ query_attribute_transformer: STRING_TRANSFORMER,
211
+ result_transformer: NOT_TRANSFORMER
212
+ },
213
+ MATCH_NOT_START_ALL: {
214
+ operator: :'start_with?',
215
+ reducer: :all?,
216
+ object_attribute_transformer: STRING_TRANSFORMER,
217
+ query_attribute_transformer: STRING_TRANSFORMER,
218
+ result_transformer: NOT_TRANSFORMER
219
+ },
220
+ MATCH_END: {
221
+ operator: :'end_with?',
222
+ object_attribute_transformer: STRING_TRANSFORMER,
223
+ query_attribute_transformer: STRING_TRANSFORMER
224
+ },
225
+ MATCH_END_ANY: {
226
+ operator: :'end_with?',
227
+ reducer: :any?,
228
+ object_attribute_transformer: STRING_TRANSFORMER,
229
+ query_attribute_transformer: STRING_TRANSFORMER
230
+ },
231
+ MATCH_END_ALL: {
232
+ operator: :'end_with?',
233
+ reducer: :all?,
234
+ object_attribute_transformer: STRING_TRANSFORMER,
235
+ query_attribute_transformer: STRING_TRANSFORMER
236
+ },
237
+ MATCH_NOT_END: {
238
+ operator: :'end_with?',
239
+ object_attribute_transformer: STRING_TRANSFORMER,
240
+ query_attribute_transformer: STRING_TRANSFORMER,
241
+ result_transformer: NOT_TRANSFORMER
242
+ },
243
+ MATCH_NOT_END_ANY: {
244
+ operator: :'end_with?',
245
+ reducer: :any?,
246
+ object_attribute_transformer: STRING_TRANSFORMER,
247
+ query_attribute_transformer: STRING_TRANSFORMER,
248
+ result_transformer: NOT_TRANSFORMER
249
+ },
250
+ MATCH_NOT_END_ALL: {
251
+ operator: :'end_with?',
252
+ reducer: :all?,
253
+ object_attribute_transformer: STRING_TRANSFORMER,
254
+ query_attribute_transformer: STRING_TRANSFORMER,
255
+ result_transformer: NOT_TRANSFORMER
256
+ },
257
+ MATCH_CONTAIN: {
258
+ operator: :'include?',
259
+ object_attribute_transformer: STRING_TRANSFORMER,
260
+ query_attribute_transformer: STRING_TRANSFORMER
261
+ },
262
+ MATCH_CONTAIN_ANY: {
263
+ operator: :'include?',
264
+ reducer: :any?,
265
+ object_attribute_transformer: STRING_TRANSFORMER,
266
+ query_attribute_transformer: STRING_TRANSFORMER
267
+ },
268
+ MATCH_CONTAIN_ALL: {
269
+ operator: :'include?',
270
+ reducer: :all?,
271
+ object_attribute_transformer: STRING_TRANSFORMER,
272
+ query_attribute_transformer: STRING_TRANSFORMER
273
+ },
274
+ MATCH_NOT_CONTAIN: {
275
+ operator: :'include?',
276
+ object_attribute_transformer: STRING_TRANSFORMER,
277
+ query_attribute_transformer: STRING_TRANSFORMER,
278
+ result_transformer: NOT_TRANSFORMER
279
+ },
280
+ MATCH_NOT_CONTAIN_ANY: {
281
+ operator: :'include?',
282
+ reducer: :any?,
283
+ object_attribute_transformer: STRING_TRANSFORMER,
284
+ query_attribute_transformer: STRING_TRANSFORMER,
285
+ result_transformer: NOT_TRANSFORMER
286
+ },
287
+ MATCH_NOT_CONTAIN_ALL: {
288
+ operator: :'include?',
289
+ reducer: :all?,
290
+ object_attribute_transformer: STRING_TRANSFORMER,
291
+ query_attribute_transformer: STRING_TRANSFORMER,
292
+ result_transformer: NOT_TRANSFORMER
293
+ }
294
+ }.freeze
295
+
296
+ def self.get(operator_name)
297
+ operator_key = operator_name.to_s.upcase.to_sym
298
+
299
+ base_operator_hash = Constants::PREDICATES.fetch(operator_key, {})
300
+ this_operator_hash = Operators::PREDICATES.fetch(operator_key, {})
301
+
302
+ base_operator_hash.merge(this_operator_hash)
303
+ end
304
+ end
305
+ # rubocop:enable Metrics/ModuleLength
306
+ end
307
+ end
308
+ end