procore-sift 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +82 -38
- data/lib/procore-sift.rb +2 -2
- data/lib/sift/filter.rb +5 -2
- data/lib/sift/sort.rb +1 -0
- data/lib/sift/subset_comparator.rb +2 -0
- data/lib/sift/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf5b2ef9c9c924ef031b2626d1acc7a89fe5fce882410c01ff0d0b784640e9be
|
4
|
+
data.tar.gz: 5adf8202ac47b3cfeea5244480de98a27737fad342a8c138d3338b0dd7eb27f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b0e77176f7c0648832374c63f60087695519ba1878e4ad325bd13453d9c77c584cb25d975d2ec129fb42b20ce8abc1afd1fc33e0e1ed0dc92af4108d96adf05
|
7
|
+
data.tar.gz: e633d786d9dbafd79f551e8c41dd6e1031658a4c299c2b6d11a4821561fde62b98b47696c0820f7800d464c0e69cd53a240880d7959bde837981e83ea00598f2
|
data/README.md
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
A tool to build your own filters and sorts with Rails and Active Record!
|
6
6
|
|
7
7
|
## Developer Usage
|
8
|
+
|
8
9
|
Include Sift in your controllers, and define some filters.
|
9
10
|
|
10
11
|
```ruby
|
@@ -27,7 +28,7 @@ Sift will also handle rendering errors using the standard rails errors structure
|
|
27
28
|
before_action :render_filter_errors, unless: :filters_valid?
|
28
29
|
|
29
30
|
def render_filter_errors
|
30
|
-
render json: { errors: filter_errors }
|
31
|
+
render json: { errors: filter_errors }, status: :bad_request && return
|
31
32
|
end
|
32
33
|
```
|
33
34
|
|
@@ -36,19 +37,22 @@ to your controller.
|
|
36
37
|
These errors are based on the type that you told sift your param was.
|
37
38
|
|
38
39
|
### Filter Types
|
40
|
+
|
39
41
|
Every filter must have a type, so that Sift knows what to do with it. The current valid filter types are:
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
|
43
|
+
- int - Filter on an integer column
|
44
|
+
- decimal - Filter on a decimal column
|
45
|
+
- boolean - Filter on a boolean column
|
46
|
+
- string - Filter on a string column
|
47
|
+
- text - Filter on a text column
|
48
|
+
- date - Filter on a date column
|
49
|
+
- time - Filter on a time column
|
50
|
+
- datetime - Filter on a datetime column
|
51
|
+
- scope - Filter on an ActiveRecord scope
|
52
|
+
- jsonb - Filter on a jsonb column (supported only in PostgreSQL)
|
50
53
|
|
51
54
|
### Filter on Scopes
|
55
|
+
|
52
56
|
Just as your filter values are used to scope queries on a column, values you
|
53
57
|
pass to a scope filter will be used as arguments to that scope. For example:
|
54
58
|
|
@@ -75,7 +79,7 @@ Scopes that accept no arguments are currently not supported.
|
|
75
79
|
|
76
80
|
#### Accessing Params with Filter Scopes
|
77
81
|
|
78
|
-
Filters with `type: :scope` have access to the params hash by passing in the desired keys to the `scope_params`. The keys passed in will be returned as a hash with their associated values
|
82
|
+
Filters with `type: :scope` have access to the params hash by passing in the desired keys to the `scope_params`. The keys passed in will be returned as a hash with their associated values.
|
79
83
|
|
80
84
|
```ruby
|
81
85
|
class Post < ActiveRecord::Base
|
@@ -94,6 +98,7 @@ class UsersController < ApplicationController
|
|
94
98
|
end
|
95
99
|
end
|
96
100
|
```
|
101
|
+
|
97
102
|
Passing `?filters[user_posts_on_date]=10/12/20` will call the `user_posts_on_date` scope with
|
98
103
|
`10/12/20` as the the first argument, and will grab the `user_id` and `blog_id` out of the params and pass them as a hash, as the second argument.
|
99
104
|
|
@@ -111,17 +116,38 @@ end
|
|
111
116
|
```
|
112
117
|
|
113
118
|
### Filter on Ranges
|
119
|
+
|
114
120
|
Some parameter types support ranges. Ranges are expected to be a string with the bounding values separated by `...`
|
115
121
|
|
116
122
|
For example `?filters[price]=3...50` would return records with a price between 3 and 50.
|
117
123
|
|
118
124
|
The following types support ranges
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
+
|
126
|
+
- int
|
127
|
+
- decimal
|
128
|
+
- boolean
|
129
|
+
- date
|
130
|
+
- time
|
131
|
+
- datetime
|
132
|
+
|
133
|
+
### Mutating Filters
|
134
|
+
|
135
|
+
Filters can be mutated before the filter is applied using the `tap` argument. This is useful, for example, if you need to adjust the time zone of a `datetime` range filter.
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
|
139
|
+
class PostsController < ApplicationController
|
140
|
+
include Sift
|
141
|
+
|
142
|
+
filter_on :expiration, type: :datetime, tap: ->(value, params) {
|
143
|
+
value.split("...").
|
144
|
+
map do |str|
|
145
|
+
str.to_date.in_time_zone(LOCAL_TIME_ZONE)
|
146
|
+
end.
|
147
|
+
join("...")
|
148
|
+
}
|
149
|
+
end
|
150
|
+
```
|
125
151
|
|
126
152
|
### Filter on jsonb column
|
127
153
|
|
@@ -130,19 +156,22 @@ Usually JSONB columns stores values as an Array or an Object (key-value), in bot
|
|
130
156
|
**Array**
|
131
157
|
|
132
158
|
It should be sent an array in the URL Query parameters
|
133
|
-
|
159
|
+
|
160
|
+
- `?filters[metadata]=[1,2]`
|
134
161
|
|
135
162
|
**key-value**
|
136
163
|
|
137
164
|
It can be passed one or more Key values:
|
138
|
-
|
139
|
-
|
165
|
+
|
166
|
+
- `?filters[metadata]={"data_1":"test"}`
|
167
|
+
- `?filters[metadata]={"data_1":"test","data_2":"[1,2]"}`
|
140
168
|
|
141
169
|
When the value is an array, it will filter records with those values or more, for example:
|
142
170
|
|
143
|
-
|
171
|
+
- `?filters[metadata]={"data_2":"[1,2]"}`
|
144
172
|
|
145
173
|
Will return records with next values stored in the JSONB column `metadata`:
|
174
|
+
|
146
175
|
```ruby
|
147
176
|
{ data_2: 1 }
|
148
177
|
{ data_2: 2 }
|
@@ -154,9 +183,10 @@ Will return records with next values stored in the JSONB column `metadata`:
|
|
154
183
|
|
155
184
|
When the `null` value is included in the array, it will return also all the records without any value in that property, for example:
|
156
185
|
|
157
|
-
|
186
|
+
- `?filters[metadata]={"data_2":"[false,null]"}`
|
158
187
|
|
159
188
|
Will return records with next values stored in the JSONB column `metadata`:
|
189
|
+
|
160
190
|
```ruby
|
161
191
|
{ data_2: null }
|
162
192
|
{ data_2: false }
|
@@ -165,9 +195,11 @@ Will return records with next values stored in the JSONB column `metadata`:
|
|
165
195
|
```
|
166
196
|
|
167
197
|
### Filter on JSON Array
|
198
|
+
|
168
199
|
`int` type filters support sending the values as an array in the URL Query parameters. For example `?filters[id]=[1,2]`. This is a way to keep payloads smaller for GET requests. When URI encoded this will become `filters%5Bid%5D=%5B1,2%5D` which is much smaller the standard format of `filters%5Bid%5D%5B%5D=1&&filters%5Bid%5D%5B%5D=2`.
|
169
200
|
|
170
201
|
On the server side, the params will be received as:
|
202
|
+
|
171
203
|
```ruby
|
172
204
|
# JSON array encoded result
|
173
205
|
"filters"=>{"id"=>"[1,2]"}
|
@@ -177,34 +209,41 @@ On the server side, the params will be received as:
|
|
177
209
|
```
|
178
210
|
|
179
211
|
Note that this feature cannot currently be wrapped in an array and should not be used in combination with sending array parameters individually.
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
212
|
+
|
213
|
+
- `?filters[id][]=[1,2]` => invalid
|
214
|
+
- `?filters[id][]=[1,2]&filters[id][]=3` => invalid
|
215
|
+
- `?filters[id]=[1,2]&filters[id]=3` => valid but only 3 is passed through to the server
|
216
|
+
- `?filters[id]=[1,2]` => valid
|
184
217
|
|
185
218
|
#### A note on encoding for JSON Array feature
|
219
|
+
|
186
220
|
JSON arrays contain the reserved characters "`,`" and "`[`" and "`]`". When encoding a JSON array in the URL there are two different ways to handle the encoding. Both ways are supported by Rails.
|
187
221
|
For example, lets look at the following filter with a JSON array `?filters[id]=[1,2]`:
|
188
|
-
|
189
|
-
|
222
|
+
|
223
|
+
- `?filters%5Bid%5D=%5B1,2%5D`
|
224
|
+
- `?filters%5Bid%5D%3D%5B1%2C2%5D`
|
190
225
|
|
191
226
|
In both cases Rails will correctly decode to the expected result of
|
227
|
+
|
192
228
|
```ruby
|
193
229
|
{ "filters" => { "id" => "[1,2]" } }
|
194
230
|
```
|
195
231
|
|
196
232
|
### Sort Types
|
233
|
+
|
197
234
|
Every sort must have a type, so that Sift knows what to do with it. The current valid sort types are:
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
235
|
+
|
236
|
+
- int - Sort on an integer column
|
237
|
+
- decimal - Sort on a decimal column
|
238
|
+
- string - Sort on a string column
|
239
|
+
- text - Sort on a text column
|
240
|
+
- date - Sort on a date column
|
241
|
+
- time - Sort on a time column
|
242
|
+
- datetime - Sort on a datetime column
|
243
|
+
- scope - Sort on an ActiveRecord scope
|
206
244
|
|
207
245
|
### Sort on Scopes
|
246
|
+
|
208
247
|
Just as your sort values are used to scope queries on a column, values you
|
209
248
|
pass to a scope sort will be used as arguments to that scope. For example:
|
210
249
|
|
@@ -240,7 +279,6 @@ Scopes that accept no arguments are currently supported, but you should note tha
|
|
240
279
|
|
241
280
|
`scope_params` can also accept symbols that are keys in the `params` hash. The value will be fetched and passed on as an argument to the scope.
|
242
281
|
|
243
|
-
|
244
282
|
## Consumer Usage
|
245
283
|
|
246
284
|
Filter:
|
@@ -255,6 +293,7 @@ Sort is translated to Active Record `order` The sorts are applied in the order t
|
|
255
293
|
the `-` symbol means to sort in `desc` order. By default, keys are sorted in `asc` order.
|
256
294
|
|
257
295
|
## Installation
|
296
|
+
|
258
297
|
Add this line to your application's Gemfile:
|
259
298
|
|
260
299
|
```ruby
|
@@ -262,11 +301,13 @@ gem 'procore-sift'
|
|
262
301
|
```
|
263
302
|
|
264
303
|
And then execute:
|
304
|
+
|
265
305
|
```bash
|
266
306
|
$ bundle
|
267
307
|
```
|
268
308
|
|
269
309
|
Or install it yourself as:
|
310
|
+
|
270
311
|
```bash
|
271
312
|
$ gem install procore-sift
|
272
313
|
```
|
@@ -278,6 +319,7 @@ We have some future plans to remove the rails dependency so that other framework
|
|
278
319
|
## Contributing
|
279
320
|
|
280
321
|
Running tests:
|
322
|
+
|
281
323
|
```bash
|
282
324
|
$ bundle exec rake test
|
283
325
|
```
|
@@ -290,6 +332,7 @@ When a bump is desired, the gemspec should have the version number bumped and me
|
|
290
332
|
|
291
333
|
Step 1: build the new version
|
292
334
|
`gem build sift.gemspec`
|
335
|
+
|
293
336
|
```
|
294
337
|
Successfully built RubyGem
|
295
338
|
Name: procore-sift
|
@@ -299,6 +342,7 @@ Step 1: build the new version
|
|
299
342
|
|
300
343
|
Step2: Push the updated build
|
301
344
|
`gem push procore-sift-0.14.0.gem`
|
345
|
+
|
302
346
|
```
|
303
347
|
Pushing gem to https://rubygems.org...
|
304
348
|
Successfully registered gem: procore-sift (0.14.0)
|
data/lib/procore-sift.rb
CHANGED
@@ -66,8 +66,8 @@ module Sift
|
|
66
66
|
end
|
67
67
|
|
68
68
|
class_methods do
|
69
|
-
def filter_on(parameter, type:, internal_name: parameter, default: nil, validate: nil, scope_params: [])
|
70
|
-
filters << Filter.new(parameter, type, internal_name, default, validate, scope_params)
|
69
|
+
def filter_on(parameter, type:, internal_name: parameter, default: nil, validate: nil, scope_params: [], tap: nil)
|
70
|
+
filters << Filter.new(parameter, type, internal_name, default, validate, scope_params, tap)
|
71
71
|
end
|
72
72
|
|
73
73
|
def filters
|
data/lib/sift/filter.rb
CHANGED
@@ -4,11 +4,12 @@ module Sift
|
|
4
4
|
class Filter
|
5
5
|
attr_reader :parameter, :default, :custom_validate, :scope_params
|
6
6
|
|
7
|
-
def initialize(param, type, internal_name, default, custom_validate = nil, scope_params = [])
|
7
|
+
def initialize(param, type, internal_name, default, custom_validate = nil, scope_params = [], tap = ->(value, _params) { value })
|
8
8
|
@parameter = Parameter.new(param, type, internal_name)
|
9
9
|
@default = default
|
10
10
|
@custom_validate = custom_validate
|
11
11
|
@scope_params = scope_params
|
12
|
+
@tap = tap
|
12
13
|
raise ArgumentError, "scope_params must be an array of symbols" unless valid_scope_params?(scope_params)
|
13
14
|
raise "unknown filter type: #{type}" unless type_validator.valid_type?
|
14
15
|
end
|
@@ -24,7 +25,9 @@ module Sift
|
|
24
25
|
elsif should_apply_default?(value)
|
25
26
|
default.call(collection)
|
26
27
|
else
|
27
|
-
|
28
|
+
parameterized_values = parameterize(value)
|
29
|
+
processed_values = @tap.present? ? @tap.call(parameterized_values, params) : parameterized_values
|
30
|
+
handler.call(collection, processed_values, params, scope_params)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
# rubocop:enable Lint/UnusedMethodArgument
|
data/lib/sift/sort.rb
CHANGED
@@ -17,6 +17,7 @@ module Sift
|
|
17
17
|
def initialize(param, type, internal_name = param, scope_params = [])
|
18
18
|
raise "unknown filter type: #{type}" unless WHITELIST_TYPES.include?(type)
|
19
19
|
raise "scope params must be an array" unless scope_params.is_a?(Array)
|
20
|
+
|
20
21
|
@parameter = Parameter.new(param, type, internal_name)
|
21
22
|
@scope_params = scope_params
|
22
23
|
end
|
data/lib/sift/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: procore-sift
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Procore Technologies
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -139,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
139
|
- !ruby/object:Gem::Version
|
140
140
|
version: '0'
|
141
141
|
requirements: []
|
142
|
-
rubygems_version: 3.
|
142
|
+
rubygems_version: 3.0.3
|
143
143
|
signing_key:
|
144
144
|
specification_version: 4
|
145
145
|
summary: Summary of Sift.
|