filterameter 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -8
- data/lib/filterameter/coordinators/base.rb +0 -7
- data/lib/filterameter/coordinators/controller_coordinator.rb +0 -2
- data/lib/filterameter/declarative_controller_filters.rb +0 -3
- data/lib/filterameter/declarative_filters.rb +0 -4
- data/lib/filterameter/exceptions/cannot_determine_model_error.rb +2 -2
- data/lib/filterameter/exceptions.rb +0 -4
- data/lib/filterameter/filter_declaration.rb +0 -1
- data/lib/filterameter/filter_factory.rb +0 -9
- data/lib/filterameter/options/partial_options.rb +64 -62
- data/lib/filterameter/parameters_base.rb +0 -1
- data/lib/filterameter/query_builder.rb +1 -9
- data/lib/filterameter/version.rb +1 -1
- data/lib/filterameter.rb +4 -10
- metadata +29 -16
- data/MIT-LICENSE +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65c8829537f7ee2affcc40a56fb5de2b58d4789fc6d1e9811b33607c86c9c01b
|
4
|
+
data.tar.gz: e731021c3cda4e0330b2a7bc499b90ceb49cd918ddd635d57a37c4bf2ce3a9bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20d94a91e915e4f7048db9d11b9608c6f7eaa3d47c018a5ff5132d63736c54e1be96b5ce7f1050325d610c7009e1b64582a2f7253f0cd6a8b37e1e65f4f0f37f
|
7
|
+
data.tar.gz: f5aa757afd07c03e2654f11cd34b348c3d0d810231ac9831c82b04e936bb9009fb20f6a8fd93b2193ddfe344481053c0b608d2a074843972d6a35b37f194329a
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/d9d87f9ce8020eb6e656/maintainability)](https://codeclimate.com/github/RockSolt/filterameter/maintainability)
|
5
5
|
|
6
6
|
# Filterameter
|
7
|
-
Declarative filter parameters provide
|
7
|
+
Declarative filter parameters provide clean and clear filters for queries.
|
8
8
|
|
9
9
|
## Usage
|
10
10
|
Declare filters in query classes or controllers to increase readability and reduce boilerplate code. Filters can be declared for attributes, scopes, or attributes from singular associations (`belongs_to` or `has_one`). Validations can also be assigned.
|
@@ -170,22 +170,42 @@ Or install it yourself as:
|
|
170
170
|
$ gem install filterameter
|
171
171
|
```
|
172
172
|
|
173
|
+
## Forms and Query Parameters
|
174
|
+
|
175
|
+
The controller mixin will look for filter parameters nested under the `filter` key. For example, here's what the query parameters might look like for size and color:
|
176
|
+
|
177
|
+
```
|
178
|
+
?filter[size]=large&filter[color]=blue
|
179
|
+
```
|
180
|
+
|
181
|
+
On [a generic search form](https://guides.rubyonrails.org/form_helpers.html#a-generic-search-form), the [`form_with` form helper takes the option `scope`](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with) that allows parameters to be grouped:
|
182
|
+
|
183
|
+
```erb
|
184
|
+
<%= form_with url: "/search", scope: :filter, method: :get do |form| %>
|
185
|
+
<%= form.label :size, "Size:" %>
|
186
|
+
<%= form.text_field :size %>
|
187
|
+
<%= form.label :color, "Color:" %>
|
188
|
+
<%= form.text_field :color %>
|
189
|
+
<%= form.submit "Search" %>
|
190
|
+
<% end %>
|
191
|
+
```
|
192
|
+
|
173
193
|
|
174
194
|
## Running Tests
|
175
195
|
|
176
|
-
Tests are written in RSpec and the dummy app uses a docker database.
|
196
|
+
Tests are written in RSpec and the dummy app uses a docker database. The script `bin/start_db.sh` starts and prepares the test
|
197
|
+
database. It is a one-time step before running the tests.
|
177
198
|
|
178
199
|
```bash
|
179
|
-
|
180
|
-
|
181
|
-
bundle exec rails db:test:prepare
|
182
|
-
cd ../..
|
200
|
+
bin/start_db.rb
|
201
|
+
bundle exec rspec
|
183
202
|
```
|
184
203
|
|
185
|
-
|
204
|
+
The tests can also be run across all the ruby and Rails combinations using appraisal. The install is also a one-time step.
|
186
205
|
|
187
206
|
```bash
|
188
|
-
bundle exec
|
207
|
+
bundle exec appraisal install
|
208
|
+
bundle exec appraisal rspec
|
189
209
|
```
|
190
210
|
|
191
211
|
## License
|
@@ -1,12 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'filterameter/filter_declaration'
|
4
|
-
require 'filterameter/filter_factory'
|
5
|
-
require 'filterameter/filter_registry'
|
6
|
-
require 'filterameter/log_subscriber'
|
7
|
-
require 'filterameter/parameters_base'
|
8
|
-
require 'filterameter/query_builder'
|
9
|
-
|
10
3
|
module Filterameter
|
11
4
|
module Coordinators
|
12
5
|
# = Coordinators Base
|
@@ -9,8 +9,8 @@ module Filterameter
|
|
9
9
|
# explicitly by adding a call to `filter_model`.
|
10
10
|
class CannotDetermineModelError < FilterameterError
|
11
11
|
def initialize(name, path)
|
12
|
-
super
|
13
|
-
"or path #{value_and_classify(path)}. Declare the model explicitly with filter_model."
|
12
|
+
super("Cannot determine model name from controller name #{value_and_classify(name)} " \
|
13
|
+
"or path #{value_and_classify(path)}. Declare the model explicitly with filter_model.")
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
@@ -1,14 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'filterameter/filters/arel_filter'
|
4
|
-
require 'filterameter/filters/attribute_filter'
|
5
|
-
require 'filterameter/filters/conditional_scope_filter'
|
6
|
-
require 'filterameter/filters/matches_filter'
|
7
|
-
require 'filterameter/filters/maximum_filter'
|
8
|
-
require 'filterameter/filters/minimum_filter'
|
9
|
-
require 'filterameter/filters/nested_filter'
|
10
|
-
require 'filterameter/filters/scope_filter'
|
11
|
-
|
12
3
|
module Filterameter
|
13
4
|
# = Filter Factory
|
14
5
|
#
|
@@ -1,82 +1,84 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
3
|
+
module Filterameter
|
4
|
+
module Options
|
5
|
+
# = Partial Options
|
6
|
+
#
|
7
|
+
# Class PartialOptions parses the options passed in as partial, then exposes those. Here are the options along with
|
8
|
+
# their valid values:
|
9
|
+
# - match: anywhere (default), from_start, dynamic
|
10
|
+
# - case_sensitive: true, false (default)
|
11
|
+
#
|
12
|
+
# Options may be specified by passing a hash with the option keys:
|
13
|
+
#
|
14
|
+
# partial: { match: :from_start, case_sensitive: true }
|
15
|
+
#
|
16
|
+
# There are two shortcuts: the partial option can be declared with `true`, which just uses the defaults; or the
|
17
|
+
# partial option can be declared with the match option directly, such as partial: :from_start.
|
18
|
+
class PartialOptions
|
19
|
+
VALID_OPTIONS = %i[match case_sensitive].freeze
|
20
|
+
VALID_MATCH_OPTIONS = %w[anywhere from_start dynamic].freeze
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def initialize(options)
|
23
|
+
@match = 'anywhere'
|
24
|
+
@case_sensitive = false
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
case options
|
27
|
+
when TrueClass
|
28
|
+
nil
|
29
|
+
when Hash
|
30
|
+
evaluate_hash(options)
|
31
|
+
when String, Symbol
|
32
|
+
assign_match(options)
|
33
|
+
end
|
32
34
|
end
|
33
|
-
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def case_sensitive?
|
37
|
+
@case_sensitive
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def match_anywhere?
|
41
|
+
@match == 'anywhere'
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
def match_from_start?
|
45
|
+
@match == 'from_start'
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def match_dynamically?
|
49
|
+
@match == 'dynamic'
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
+
private
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
def evaluate_hash(options)
|
55
|
+
options.assert_valid_keys(:match, :case_sensitive)
|
56
|
+
assign_match(options[:match]) if options.key?(:match)
|
57
|
+
assign_case_sensitive(options[:case_sensitive]) if options.key?(:case_sensitive)
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
def assign_match(value)
|
61
|
+
validate_match(value)
|
62
|
+
@match = value.to_s
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
65
|
+
def validate_match(value)
|
66
|
+
return if VALID_MATCH_OPTIONS.include? value.to_s
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
raise ArgumentError,
|
69
|
+
"Invalid match option for partial: #{value}. Valid options are #{VALID_MATCH_OPTIONS.to_sentence}"
|
70
|
+
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
def assign_case_sensitive(value)
|
73
|
+
validate_case_sensitive(value)
|
74
|
+
@case_sensitive = value
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
def validate_case_sensitive(value)
|
78
|
+
return if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
78
79
|
|
79
|
-
|
80
|
+
raise ArgumentError, "Invalid case_sensitive option for partial: #{value}. Valid options are true and false."
|
81
|
+
end
|
80
82
|
end
|
81
83
|
end
|
82
84
|
end
|
@@ -64,15 +64,7 @@ module Filterameter
|
|
64
64
|
raise Filterameter::Exceptions::ValidationError, validator.errors
|
65
65
|
end
|
66
66
|
|
67
|
-
filter_params.except(*
|
68
|
-
end
|
69
|
-
|
70
|
-
def invalid_attributes(errors)
|
71
|
-
if errors.respond_to? :attribute_names
|
72
|
-
errors.attribute_names
|
73
|
-
else # pre rails 6.1
|
74
|
-
errors.keys
|
75
|
-
end
|
67
|
+
filter_params.except(*validator.errors.attribute_names.map(&:to_s))
|
76
68
|
end
|
77
69
|
|
78
70
|
def validator_class
|
data/lib/filterameter/version.rb
CHANGED
data/lib/filterameter.rb
CHANGED
@@ -1,17 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
require 'zeitwerk'
|
4
|
+
|
5
|
+
loader = Zeitwerk::Loader.for_gem
|
6
|
+
loader.setup # ready!
|
7
7
|
|
8
8
|
# = Filterameter
|
9
|
-
#
|
10
|
-
# Module Filterameter can be mixed into a controller to provide the DSL to describe each controller's filters.
|
11
|
-
#
|
12
|
-
# The model class must be declared if it cannot be derived. It can be derived if (A) the model is not namespaced and its
|
13
|
-
# name matches the controller name (for example BrandsController -> Brand) or (B) both the controller and model share
|
14
|
-
# the same namespace and name.
|
15
9
|
module Filterameter
|
16
10
|
class << self
|
17
11
|
attr_writer :configuration
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filterameter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Kummer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '6.1'
|
20
20
|
type: :runtime
|
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:
|
26
|
+
version: '6.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: appraisal
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 2.5.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
40
|
+
version: 2.5.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: guard
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,56 +86,70 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
89
|
+
version: 1.5.4
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
96
|
+
version: 1.5.4
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec-rails
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '6.1'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '6.1'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rubocop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.60.2
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.
|
124
|
+
version: 1.60.2
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-packaging
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.5.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.5.2
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: rubocop-rails
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
145
|
+
version: 2.23.1
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: 2.
|
152
|
+
version: 2.23.1
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: simplecov
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,7 +171,6 @@ executables: []
|
|
157
171
|
extensions: []
|
158
172
|
extra_rdoc_files: []
|
159
173
|
files:
|
160
|
-
- MIT-LICENSE
|
161
174
|
- README.md
|
162
175
|
- Rakefile
|
163
176
|
- lib/filterameter.rb
|
@@ -208,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
221
|
- !ruby/object:Gem::Version
|
209
222
|
version: '0'
|
210
223
|
requirements: []
|
211
|
-
rubygems_version: 3.
|
224
|
+
rubygems_version: 3.4.19
|
212
225
|
signing_key:
|
213
226
|
specification_version: 4
|
214
227
|
summary: Declarative Filter Parameters
|
data/MIT-LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright 2019 Todd Kummer
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|