json_api_filter 0.3.2 → 0.4.0

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: 5471c30a61e8ea40ce7e68b4ce5782c7a690bb9ec05db87b4945e43d1c0e1e0a
4
- data.tar.gz: 8aea59cea05e034f6f33e8405fe1faa939fbf558887f704d296c7c6033b993b0
3
+ metadata.gz: 26dba474ac325ef0b01c1f2a6046d94ec4883e497eb892fc5646744eb0e67273
4
+ data.tar.gz: 627dffb840e95036c4617175345702278c6221f7fc513033b94d8eb0b343e0cc
5
5
  SHA512:
6
- metadata.gz: c4ef69f9954823df0f90f60f092c1bc948960096a7a61ddd16c8bc6d17f29eacf40a050ba9f203790ac5063a5868ce2f60a88fb2ed758117e0a000e74abe6ebd
7
- data.tar.gz: 35d7ffff9ff7e409633e81701ead53db2ee8267fb54e768b4698c697a75c1ea5ff6afb4d66709713ea6765969b0eac35d88c70bd5f3279812d3f53ab8b11be93
6
+ metadata.gz: b6afe3cc8426481a78cf30287ccd153c5f55c981b593a533e3f1941d376b5e72453dd4537a478b73b5600154559d57529390d66cadc87380be78036897b4ef22
7
+ data.tar.gz: 607c4107b32a551de880edccd2f10c86711fa45250120756bd390eff953ed44677e9c28a69ecc19ec5b0ed832a76f4d024684198897ef9847d6c710ecb6d7751
@@ -1,6 +1,7 @@
1
1
  name: Ruby Gem
2
2
 
3
3
  on:
4
+ pull_request:
4
5
  push:
5
6
  branches: [ master ]
6
7
 
@@ -13,13 +14,25 @@ jobs:
13
14
  packages: write
14
15
 
15
16
  steps:
16
- - uses: actions/checkout@v2
17
- - name: Set up Ruby 2.6
18
- uses: actions/setup-ruby@v1
17
+ - uses: actions/checkout@v4
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
19
20
  with:
20
- ruby-version: 2.6.x
21
+ ruby-version: 3.3.4
22
+ bundler: 2.5.11
23
+ bundler-cache: true
24
+
25
+ - name: Set up the test database
26
+ run: |
27
+ bundle install
28
+ bundle exec rails db:setup
29
+ working-directory: spec/dummy
30
+
31
+ - name: Run tests
32
+ run: bundle exec rspec
21
33
 
22
34
  - name: Publish to RubyGems
35
+ if: github.event_name == 'push'
23
36
  run: |
24
37
  mkdir -p $HOME/.gem
25
38
  touch $HOME/.gem/credentials
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.4
data/.travis.yml CHANGED
@@ -3,8 +3,9 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.6.3
7
- before_install: gem install bundler -v 1.17.2
6
+ - 3.3.4
7
+ before_install: gem install bundler -v 2.5.11
8
8
  script:
9
+ - (cd spec/dummy && bundle install)
9
10
  - (cd spec/dummy && RAILS_ENV=test bundle exec rails db:setup)
10
11
  - bundle exec rspec
data/Gemfile.lock CHANGED
@@ -1,175 +1,249 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json_api_filter (0.3.2)
4
+ json_api_filter (0.4.0)
5
5
  activesupport (>= 3.0.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actioncable (6.1.3.1)
11
- actionpack (= 6.1.3.1)
12
- activesupport (= 6.1.3.1)
10
+ actioncable (7.1.6)
11
+ actionpack (= 7.1.6)
12
+ activesupport (= 7.1.6)
13
13
  nio4r (~> 2.0)
14
14
  websocket-driver (>= 0.6.1)
15
- actionmailbox (6.1.3.1)
16
- actionpack (= 6.1.3.1)
17
- activejob (= 6.1.3.1)
18
- activerecord (= 6.1.3.1)
19
- activestorage (= 6.1.3.1)
20
- activesupport (= 6.1.3.1)
15
+ zeitwerk (~> 2.6)
16
+ actionmailbox (7.1.6)
17
+ actionpack (= 7.1.6)
18
+ activejob (= 7.1.6)
19
+ activerecord (= 7.1.6)
20
+ activestorage (= 7.1.6)
21
+ activesupport (= 7.1.6)
21
22
  mail (>= 2.7.1)
22
- actionmailer (6.1.3.1)
23
- actionpack (= 6.1.3.1)
24
- actionview (= 6.1.3.1)
25
- activejob (= 6.1.3.1)
26
- activesupport (= 6.1.3.1)
23
+ net-imap
24
+ net-pop
25
+ net-smtp
26
+ actionmailer (7.1.6)
27
+ actionpack (= 7.1.6)
28
+ actionview (= 7.1.6)
29
+ activejob (= 7.1.6)
30
+ activesupport (= 7.1.6)
27
31
  mail (~> 2.5, >= 2.5.4)
28
- rails-dom-testing (~> 2.0)
29
- actionpack (6.1.3.1)
30
- actionview (= 6.1.3.1)
31
- activesupport (= 6.1.3.1)
32
- rack (~> 2.0, >= 2.0.9)
32
+ net-imap
33
+ net-pop
34
+ net-smtp
35
+ rails-dom-testing (~> 2.2)
36
+ actionpack (7.1.6)
37
+ actionview (= 7.1.6)
38
+ activesupport (= 7.1.6)
39
+ cgi
40
+ nokogiri (>= 1.8.5)
41
+ racc
42
+ rack (>= 2.2.4)
43
+ rack-session (>= 1.0.1)
33
44
  rack-test (>= 0.6.3)
34
- rails-dom-testing (~> 2.0)
35
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
- actiontext (6.1.3.1)
37
- actionpack (= 6.1.3.1)
38
- activerecord (= 6.1.3.1)
39
- activestorage (= 6.1.3.1)
40
- activesupport (= 6.1.3.1)
45
+ rails-dom-testing (~> 2.2)
46
+ rails-html-sanitizer (~> 1.6)
47
+ actiontext (7.1.6)
48
+ actionpack (= 7.1.6)
49
+ activerecord (= 7.1.6)
50
+ activestorage (= 7.1.6)
51
+ activesupport (= 7.1.6)
52
+ globalid (>= 0.6.0)
41
53
  nokogiri (>= 1.8.5)
42
- actionview (6.1.3.1)
43
- activesupport (= 6.1.3.1)
54
+ actionview (7.1.6)
55
+ activesupport (= 7.1.6)
44
56
  builder (~> 3.1)
45
- erubi (~> 1.4)
46
- rails-dom-testing (~> 2.0)
47
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
- activejob (6.1.3.1)
49
- activesupport (= 6.1.3.1)
57
+ cgi
58
+ erubi (~> 1.11)
59
+ rails-dom-testing (~> 2.2)
60
+ rails-html-sanitizer (~> 1.6)
61
+ activejob (7.1.6)
62
+ activesupport (= 7.1.6)
50
63
  globalid (>= 0.3.6)
51
- activemodel (6.1.3.1)
52
- activesupport (= 6.1.3.1)
53
- activerecord (6.1.3.1)
54
- activemodel (= 6.1.3.1)
55
- activesupport (= 6.1.3.1)
56
- activestorage (6.1.3.1)
57
- actionpack (= 6.1.3.1)
58
- activejob (= 6.1.3.1)
59
- activerecord (= 6.1.3.1)
60
- activesupport (= 6.1.3.1)
61
- marcel (~> 1.0.0)
62
- mini_mime (~> 1.0.2)
63
- activesupport (6.1.3.1)
64
+ activemodel (7.1.6)
65
+ activesupport (= 7.1.6)
66
+ activerecord (7.1.6)
67
+ activemodel (= 7.1.6)
68
+ activesupport (= 7.1.6)
69
+ timeout (>= 0.4.0)
70
+ activestorage (7.1.6)
71
+ actionpack (= 7.1.6)
72
+ activejob (= 7.1.6)
73
+ activerecord (= 7.1.6)
74
+ activesupport (= 7.1.6)
75
+ marcel (~> 1.0)
76
+ activesupport (7.1.6)
77
+ base64
78
+ benchmark (>= 0.3)
79
+ bigdecimal
64
80
  concurrent-ruby (~> 1.0, >= 1.0.2)
81
+ connection_pool (>= 2.2.5)
82
+ drb
65
83
  i18n (>= 1.6, < 2)
84
+ logger (>= 1.4.2)
66
85
  minitest (>= 5.1)
86
+ mutex_m
87
+ securerandom (>= 0.3)
67
88
  tzinfo (~> 2.0)
68
- zeitwerk (~> 2.3)
69
- builder (3.2.4)
70
- byebug (11.1.3)
71
- concurrent-ruby (1.1.8)
72
- crass (1.0.6)
73
- diff-lcs (1.4.4)
74
- erubi (1.10.0)
75
- globalid (0.4.2)
76
- activesupport (>= 4.2.0)
77
- i18n (1.8.10)
89
+ base64 (0.3.0)
90
+ benchmark (0.5.0)
91
+ bigdecimal (4.1.2)
92
+ builder (3.3.0)
93
+ byebug (13.0.0)
94
+ reline (>= 0.6.0)
95
+ cgi (0.5.2)
96
+ concurrent-ruby (1.3.8)
97
+ connection_pool (3.0.2)
98
+ crass (1.0.7)
99
+ date (3.5.1)
100
+ diff-lcs (1.6.2)
101
+ drb (2.2.3)
102
+ erb (6.0.7)
103
+ erubi (1.13.1)
104
+ globalid (1.4.0)
105
+ activesupport (>= 6.1)
106
+ i18n (1.15.2)
78
107
  concurrent-ruby (~> 1.0)
79
- loofah (2.9.0)
108
+ io-console (0.9.2)
109
+ irb (1.18.0)
110
+ pp (>= 0.6.0)
111
+ prism (>= 1.3.0)
112
+ rdoc (>= 4.0.0)
113
+ reline (>= 0.4.2)
114
+ logger (1.7.0)
115
+ loofah (2.25.2)
80
116
  crass (~> 1.0.2)
81
- nokogiri (>= 1.5.9)
82
- mail (2.7.1)
117
+ nokogiri (>= 1.12.0)
118
+ mail (2.9.1)
119
+ logger
83
120
  mini_mime (>= 0.1.1)
84
- marcel (1.0.1)
85
- method_source (1.0.0)
86
- mini_mime (1.0.3)
87
- mini_portile2 (2.6.1)
88
- minitest (5.14.4)
89
- nio4r (2.5.7)
90
- nokogiri (1.12.5)
91
- mini_portile2 (~> 2.6.1)
121
+ net-imap
122
+ net-pop
123
+ net-smtp
124
+ marcel (1.2.1)
125
+ mini_mime (1.1.5)
126
+ mini_portile2 (2.8.9)
127
+ minitest (6.0.6)
128
+ drb (~> 2.0)
129
+ prism (~> 1.5)
130
+ mutex_m (0.3.0)
131
+ net-imap (0.6.6)
132
+ date
133
+ net-protocol
134
+ net-pop (0.1.2)
135
+ net-protocol
136
+ net-protocol (0.3.0)
137
+ timeout
138
+ net-smtp (0.5.1)
139
+ net-protocol
140
+ nio4r (2.7.5)
141
+ nokogiri (1.19.4)
142
+ mini_portile2 (~> 2.8.2)
92
143
  racc (~> 1.4)
93
- racc (1.5.2)
94
- rack (2.2.3)
95
- rack-test (1.1.0)
96
- rack (>= 1.0, < 3)
97
- rails (6.1.3.1)
98
- actioncable (= 6.1.3.1)
99
- actionmailbox (= 6.1.3.1)
100
- actionmailer (= 6.1.3.1)
101
- actionpack (= 6.1.3.1)
102
- actiontext (= 6.1.3.1)
103
- actionview (= 6.1.3.1)
104
- activejob (= 6.1.3.1)
105
- activemodel (= 6.1.3.1)
106
- activerecord (= 6.1.3.1)
107
- activestorage (= 6.1.3.1)
108
- activesupport (= 6.1.3.1)
144
+ pp (0.6.4)
145
+ prettyprint
146
+ prettyprint (0.2.0)
147
+ prism (1.9.0)
148
+ racc (1.8.1)
149
+ rack (3.2.7)
150
+ rack-session (2.1.2)
151
+ base64 (>= 0.1.0)
152
+ rack (>= 3.0.0)
153
+ rack-test (2.2.0)
154
+ rack (>= 1.3)
155
+ rackup (2.3.1)
156
+ rack (>= 3)
157
+ rails (7.1.6)
158
+ actioncable (= 7.1.6)
159
+ actionmailbox (= 7.1.6)
160
+ actionmailer (= 7.1.6)
161
+ actionpack (= 7.1.6)
162
+ actiontext (= 7.1.6)
163
+ actionview (= 7.1.6)
164
+ activejob (= 7.1.6)
165
+ activemodel (= 7.1.6)
166
+ activerecord (= 7.1.6)
167
+ activestorage (= 7.1.6)
168
+ activesupport (= 7.1.6)
109
169
  bundler (>= 1.15.0)
110
- railties (= 6.1.3.1)
111
- sprockets-rails (>= 2.0.0)
112
- rails-dom-testing (2.0.3)
113
- activesupport (>= 4.2.0)
170
+ railties (= 7.1.6)
171
+ rails-dom-testing (2.3.0)
172
+ activesupport (>= 5.0.0)
173
+ minitest
114
174
  nokogiri (>= 1.6)
115
- rails-html-sanitizer (1.3.0)
116
- loofah (~> 2.3)
117
- railties (6.1.3.1)
118
- actionpack (= 6.1.3.1)
119
- activesupport (= 6.1.3.1)
120
- method_source
121
- rake (>= 0.8.7)
122
- thor (~> 1.0)
123
- rake (13.0.3)
124
- rspec (3.10.0)
125
- rspec-core (~> 3.10.0)
126
- rspec-expectations (~> 3.10.0)
127
- rspec-mocks (~> 3.10.0)
128
- rspec-core (3.10.1)
129
- rspec-support (~> 3.10.0)
130
- rspec-expectations (3.10.1)
175
+ rails-html-sanitizer (1.7.1)
176
+ loofah (~> 2.25, >= 2.25.2)
177
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
178
+ railties (7.1.6)
179
+ actionpack (= 7.1.6)
180
+ activesupport (= 7.1.6)
181
+ cgi
182
+ irb
183
+ rackup (>= 1.0.0)
184
+ rake (>= 12.2)
185
+ thor (~> 1.0, >= 1.2.2)
186
+ tsort (>= 0.2)
187
+ zeitwerk (~> 2.6)
188
+ rake (13.4.2)
189
+ rbs (4.2.0)
190
+ logger
191
+ prism (>= 1.6.0)
192
+ tsort
193
+ rdoc (8.0.0)
194
+ erb
195
+ prism (>= 1.6.0)
196
+ rbs (>= 4.0.0)
197
+ tsort
198
+ reline (0.7.0)
199
+ io-console (~> 0.5)
200
+ rspec (3.13.2)
201
+ rspec-core (~> 3.13.0)
202
+ rspec-expectations (~> 3.13.0)
203
+ rspec-mocks (~> 3.13.0)
204
+ rspec-core (3.13.6)
205
+ rspec-support (~> 3.13.0)
206
+ rspec-expectations (3.13.5)
131
207
  diff-lcs (>= 1.2.0, < 2.0)
132
- rspec-support (~> 3.10.0)
133
- rspec-mocks (3.10.2)
208
+ rspec-support (~> 3.13.0)
209
+ rspec-mocks (3.13.8)
134
210
  diff-lcs (>= 1.2.0, < 2.0)
135
- rspec-support (~> 3.10.0)
136
- rspec-rails (5.0.1)
137
- actionpack (>= 5.2)
138
- activesupport (>= 5.2)
139
- railties (>= 5.2)
140
- rspec-core (~> 3.10)
141
- rspec-expectations (~> 3.10)
142
- rspec-mocks (~> 3.10)
143
- rspec-support (~> 3.10)
144
- rspec-support (3.10.2)
145
- sprockets (4.0.2)
146
- concurrent-ruby (~> 1.0)
147
- rack (> 1, < 3)
148
- sprockets-rails (3.2.2)
149
- actionpack (>= 4.0)
150
- activesupport (>= 4.0)
151
- sprockets (>= 3.0.0)
152
- sqlite3 (1.4.2)
153
- thor (1.1.0)
154
- tzinfo (2.0.4)
211
+ rspec-support (~> 3.13.0)
212
+ rspec-rails (7.1.1)
213
+ actionpack (>= 7.0)
214
+ activesupport (>= 7.0)
215
+ railties (>= 7.0)
216
+ rspec-core (~> 3.13)
217
+ rspec-expectations (~> 3.13)
218
+ rspec-mocks (~> 3.13)
219
+ rspec-support (~> 3.13)
220
+ rspec-support (3.13.7)
221
+ securerandom (0.4.1)
222
+ sqlite3 (2.9.6)
223
+ mini_portile2 (~> 2.8.0)
224
+ thor (1.5.0)
225
+ timeout (0.6.1)
226
+ tsort (0.2.0)
227
+ tzinfo (2.0.6)
155
228
  concurrent-ruby (~> 1.0)
156
- websocket-driver (0.7.3)
229
+ websocket-driver (0.8.2)
230
+ base64
157
231
  websocket-extensions (>= 0.1.0)
158
232
  websocket-extensions (0.1.5)
159
- zeitwerk (2.4.2)
233
+ zeitwerk (2.8.3)
160
234
 
161
235
  PLATFORMS
162
236
  ruby
163
237
 
164
238
  DEPENDENCIES
165
- bundler (~> 1.16)
239
+ bundler (~> 2.5)
166
240
  byebug
167
241
  json_api_filter!
168
- rails
242
+ rails (>= 7.1, < 7.2)
169
243
  rake (~> 13.0)
170
244
  rspec (>= 3.0)
171
245
  rspec-rails
172
246
  sqlite3
173
247
 
174
248
  BUNDLED WITH
175
- 1.17.2
249
+ 2.5.11
data/README.md CHANGED
@@ -49,11 +49,45 @@ end
49
49
 
50
50
  ```
51
51
 
52
- - `permitted_filters` let you define allowed attributes to filter on (mandatory)
52
+ - `permitted_filters` let you define allowed attributes to filter on (mandatory unless a custom filter is declared)
53
53
  - `permitted_searches` let you define the allowed search method defined in you model what will be called if you pass `search` params in your request (can be a pg_search scope)
54
54
  - `permitted_inclusions` let you define the allowed inclusions
55
55
  - `json_api_filter(scope, params)` return an active record relation (`Book::` in this example)
56
56
 
57
+ ## Custom filters
58
+
59
+ Use `filter` when the public filter name or values do not map directly to a database column. Custom filters are
60
+ permitted by their declaration and do not also belong in `permitted_filters`.
61
+
62
+ ```ruby
63
+ TYPE_MAP = {
64
+ "online" => "exam",
65
+ "paper" => "paper",
66
+ }.freeze
67
+
68
+ filter :type do
69
+ eq do |scope, values|
70
+ mapped_values = values.map { |value| TYPE_MAP[value] }
71
+
72
+ mapped_values.any?(&:nil?) ? scope.none : scope.where(quiz_type: mapped_values)
73
+ end
74
+ end
75
+ ```
76
+
77
+ Direct syntax uses the `eq` handler, so both of these requests call the block above:
78
+
79
+ ```text
80
+ /exams?filter[type]=online
81
+ /exams?filter[type][eq]=online
82
+ ```
83
+
84
+ Values are always passed as an array. Comma-separated values are split before the handler is called, so
85
+ `filter[type]=online,paper` passes `["online", "paper"]`.
86
+
87
+ The supported custom operators are the operators already understood by the gem: `eq`, `ne`, `gt`, `ge`, `lt`, and
88
+ `le`. Only declared operator blocks run. A custom filter never falls back to treating its public name as a database
89
+ column. Every handler must return an Active Record scope.
90
+
57
91
  # Use inclusions in serializers
58
92
 
59
93
  # Handling errors
@@ -11,8 +11,9 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = "Provide a filter for jsonAPI Controller in Rails"
13
13
  spec.description = ""
14
- spec.homepage = "https://github.com/Blaked84/json_api_filter"
14
+ spec.homepage = "https://github.com/evalmee/json_api_filter"
15
15
  spec.license = "MIT"
16
+ spec.required_ruby_version = ">= 3.3.4"
16
17
 
17
18
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
19
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -20,7 +21,7 @@ Gem::Specification.new do |spec|
20
21
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
22
 
22
23
  spec.metadata["homepage_uri"] = spec.homepage
23
- spec.metadata["source_code_uri"] = "https://github.com/Blaked84/json_api_filter"
24
+ spec.metadata["source_code_uri"] = "https://github.com/evalmee/json_api_filter"
24
25
  else
25
26
  raise "RubyGems 2.0 or newer is required to protect against " \
26
27
  "public gem pushes."
@@ -35,12 +36,12 @@ Gem::Specification.new do |spec|
35
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
37
  spec.require_paths = ["lib"]
37
38
 
38
- spec.add_development_dependency "bundler", "~> 1.16"
39
+ spec.add_development_dependency "bundler", "~> 2.5"
39
40
  spec.add_development_dependency "rake", "~> 13.0"
40
41
  spec.add_development_dependency "rspec", ">= 3.0"
41
42
  spec.add_development_dependency "rspec-rails"
42
43
  spec.add_development_dependency "sqlite3"
43
- spec.add_development_dependency 'rails'
44
+ spec.add_development_dependency 'rails', '>= 7.1', '< 7.2'
44
45
  spec.add_development_dependency 'byebug'
45
46
  spec.add_dependency "activesupport", ">= 3.0.0"
46
- end
47
+ end
@@ -0,0 +1,24 @@
1
+ module JsonApiFilter
2
+ class CustomFilter
3
+ OPERATORS = %i[eq ne gt ge lt le].freeze
4
+
5
+ attr_reader :handlers
6
+
7
+ def initialize(&definition)
8
+ @handlers = {}
9
+ instance_eval(&definition)
10
+ @handlers.freeze
11
+ freeze
12
+ end
13
+
14
+ OPERATORS.each do |operator|
15
+ define_method(operator) do |&handler|
16
+ handlers[operator.to_s] = handler
17
+ end
18
+ end
19
+
20
+ def handler_for(operator)
21
+ handlers[operator.to_s]
22
+ end
23
+ end
24
+ end
@@ -1,16 +1,17 @@
1
1
  module JsonApiFilter
2
2
  class Dispatch
3
3
 
4
- attr_reader :params, :scope, :allowed_filters, :allowed_searches
4
+ attr_reader :params, :scope, :allowed_filters, :allowed_searches, :custom_filters
5
5
 
6
6
  # @param [ActiveRecord::Base] scope
7
7
  # @param [Hash, ActionController::Parameters] params
8
8
  # @param [Array<Symbol>] allowed_filters
9
- def initialize(scope, params, allowed_filters:, allowed_searches:)
9
+ def initialize(scope, params, allowed_filters:, allowed_searches:, custom_filters: {})
10
10
  @params = params
11
11
  @scope = scope
12
12
  @allowed_filters = allowed_filters
13
13
  @allowed_searches = allowed_searches
14
+ @custom_filters = custom_filters
14
15
  end
15
16
 
16
17
  # @return [ActiveRecord_Relation]
@@ -32,6 +33,8 @@ module JsonApiFilter
32
33
  def filters_predicate
33
34
  #TODO: split this method
34
35
  parser_params.fetch('filter', {}).map do |key, value|
36
+ custom_filter = custom_filters[key.to_s]
37
+ next custom_filter_predicate(custom_filter, value) if custom_filter
35
38
  next unless filters.include?(key)
36
39
 
37
40
  if nested_filters.include?(key.to_sym)
@@ -39,19 +42,45 @@ module JsonApiFilter
39
42
  scope,
40
43
  {key => value},
41
44
  association: true
42
- )
45
+ ).predicate
43
46
  end
44
47
 
45
48
  if value.class != ActiveSupport::HashWithIndifferentAccess
46
- next ::JsonApiFilter::FieldFilters::Matcher.new(scope, {key => value})
49
+ next ::JsonApiFilter::FieldFilters::Matcher.new(scope, {key => value}).predicate
47
50
  end
48
51
 
49
52
  ::JsonApiFilter::FieldFilters::Compare.new(
50
53
  scope,
51
54
  {key => value},
52
55
  allowed_searches: allowed_searches
53
- )
54
- end.compact.map(&:predicate).reduce(&:merge)
56
+ ).predicate
57
+ end.compact.reduce(&:merge)
58
+ end
59
+
60
+ def custom_filter_predicate(custom_filter, value)
61
+ predicates = if value.respond_to?(:each_pair)
62
+ value.map do |operator, operator_value|
63
+ apply_custom_filter(custom_filter, operator, operator_value)
64
+ end
65
+ else
66
+ [apply_custom_filter(custom_filter, :eq, value)]
67
+ end
68
+
69
+ predicates.compact.reduce(&:merge)
70
+ end
71
+
72
+ def apply_custom_filter(custom_filter, operator, value)
73
+ handler = custom_filter.handler_for(operator)
74
+ return unless handler
75
+
76
+ handler.call(scope, custom_filter_values(value))
77
+ end
78
+
79
+ def custom_filter_values(value)
80
+ return value if value.is_a?(Array)
81
+ return ::JsonApiFilter::ValueParser.parse(value) if value.is_a?(String)
82
+
83
+ [value]
55
84
  end
56
85
 
57
86
  # @return [ActiveRecord::Base, NilClass]
@@ -1,3 +1,3 @@
1
1
  module JsonApiFilter
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require "json_api_filter/version"
2
2
  require "json_api_filter/auto_join"
3
+ require "json_api_filter/custom_filter"
3
4
  require "json_api_filter/dispatch"
4
5
  require "json_api_filter/filter_attributes"
5
6
  require "json_api_filter/value_parser"
@@ -42,7 +43,7 @@ module JsonApiFilter
42
43
 
43
44
  # @param [ActiveRecord::Base] scope
44
45
  def json_api_filter(scope, query_params = params)
45
- unless self.class.json_api_permitted_filters.present?
46
+ unless self.class.json_api_permitted_filters.present? || self.class.json_api_custom_filters.present?
46
47
  raise ::JsonApiFilter::MissingPermittedFilterError
47
48
  end
48
49
 
@@ -50,7 +51,8 @@ module JsonApiFilter
50
51
  scope,
51
52
  query_params,
52
53
  allowed_filters: self.class.json_api_permitted_filters,
53
- allowed_searches: self.class.json_api_permitted_searches
54
+ allowed_searches: self.class.json_api_permitted_searches,
55
+ custom_filters: self.class.json_api_custom_filters
54
56
  ).process
55
57
  end
56
58
 
@@ -75,6 +77,20 @@ module JsonApiFilter
75
77
  []
76
78
  end
77
79
 
80
+ def self.filter(name, &definition)
81
+ filters = json_api_custom_filters.merge(
82
+ name.to_s => ::JsonApiFilter::CustomFilter.new(&definition)
83
+ ).freeze
84
+
85
+ define_singleton_method(:json_api_custom_filters) do
86
+ filters
87
+ end
88
+ end
89
+
90
+ def self.json_api_custom_filters
91
+ {}.freeze
92
+ end
93
+
78
94
  def self.permitted_searches(global, **columns)
79
95
  define_singleton_method(:json_api_permitted_searches) do
80
96
  { global: global, columns: columns }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_api_filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blaked
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2026-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: '2.5'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: '2.5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,20 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '7.1'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '7.2'
90
93
  type: :development
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
93
96
  requirements:
94
97
  - - ">="
95
98
  - !ruby/object:Gem::Version
96
- version: '0'
99
+ version: '7.1'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '7.2'
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: byebug
99
105
  requirement: !ruby/object:Gem::Requirement
@@ -132,6 +138,7 @@ files:
132
138
  - ".github/workflows/gem-push.yml"
133
139
  - ".gitignore"
134
140
  - ".rspec"
141
+ - ".ruby-version"
135
142
  - ".travis.yml"
136
143
  - CODE_OF_CONDUCT.md
137
144
  - Gemfile
@@ -144,6 +151,7 @@ files:
144
151
  - json_api_filter.gemspec
145
152
  - lib/json_api_filter.rb
146
153
  - lib/json_api_filter/auto_join.rb
154
+ - lib/json_api_filter/custom_filter.rb
147
155
  - lib/json_api_filter/dispatch.rb
148
156
  - lib/json_api_filter/field_filters/base.rb
149
157
  - lib/json_api_filter/field_filters/compare.rb
@@ -154,14 +162,14 @@ files:
154
162
  - lib/json_api_filter/filter_attributes.rb
155
163
  - lib/json_api_filter/value_parser.rb
156
164
  - lib/json_api_filter/version.rb
157
- homepage: https://github.com/Blaked84/json_api_filter
165
+ homepage: https://github.com/evalmee/json_api_filter
158
166
  licenses:
159
167
  - MIT
160
168
  metadata:
161
169
  allowed_push_host: https://rubygems.org
162
- homepage_uri: https://github.com/Blaked84/json_api_filter
163
- source_code_uri: https://github.com/Blaked84/json_api_filter
164
- post_install_message:
170
+ homepage_uri: https://github.com/evalmee/json_api_filter
171
+ source_code_uri: https://github.com/evalmee/json_api_filter
172
+ post_install_message:
165
173
  rdoc_options: []
166
174
  require_paths:
167
175
  - lib
@@ -169,15 +177,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
177
  requirements:
170
178
  - - ">="
171
179
  - !ruby/object:Gem::Version
172
- version: '0'
180
+ version: 3.3.4
173
181
  required_rubygems_version: !ruby/object:Gem::Requirement
174
182
  requirements:
175
183
  - - ">="
176
184
  - !ruby/object:Gem::Version
177
185
  version: '0'
178
186
  requirements: []
179
- rubygems_version: 3.0.3.1
180
- signing_key:
187
+ rubygems_version: 3.5.11
188
+ signing_key:
181
189
  specification_version: 4
182
190
  summary: Provide a filter for jsonAPI Controller in Rails
183
191
  test_files: []