filterameter 0.4.2 → 0.6.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 +17 -35
- data/lib/filterameter/declarative_filters.rb +18 -8
- data/lib/filterameter/filter_coordinator.rb +60 -0
- data/lib/filterameter/filter_declaration.rb +2 -2
- data/lib/filterameter/filter_factory.rb +33 -5
- data/lib/filterameter/filter_registry.rb +2 -2
- data/lib/filterameter/filters/nested_collection_filter.rb +15 -0
- data/lib/filterameter/filters/nested_filter.rb +16 -2
- data/lib/filterameter/version.rb +1 -1
- metadata +10 -11
- data/lib/filterameter/coordinators/base.rb +0 -36
- data/lib/filterameter/coordinators/controller_coordinator.rb +0 -40
- data/lib/filterameter/coordinators/query_coordinator.rb +0 -18
- data/lib/filterameter/declarative_controller_filters.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b2ac8a6c211408669122ab5bf2a131ade58736fa145508305f5ebe3dc9c0bdb
|
4
|
+
data.tar.gz: 9216ddecfedab830f9a3a82cf9c1936f040e64664b23b2d16a4ccd71f1f4923e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad640c098660b98a33f54378f16dced7d3c2dd278c6d6b6db120d2026cb7f03bda5f0d5033653e697af153eff4bdb3c9c84e39d263a18eedba5075098b7354ef
|
7
|
+
data.tar.gz: 3e775bbe1d6ed769bdfb1a83ac3f4a74c69128517a5bf6ea3fc140e50a8b025214d87d544c9263ad4bf0495f34d477f7a2128836f81e7b6a82d4ec037b9df938
|
data/README.md
CHANGED
@@ -4,10 +4,10 @@
|
|
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 clean and clear filters for
|
7
|
+
Declarative filter parameters provide clean and clear filters for Rails controllers.
|
8
8
|
|
9
9
|
## Usage
|
10
|
-
Declare filters in
|
10
|
+
Declare filters in controllers to increase readability and reduce boilerplate code. Filters can be declared for attributes or scopes, either directly on the model or on an associated model. Validations can also be assigned.
|
11
11
|
|
12
12
|
```ruby
|
13
13
|
filter :color
|
@@ -28,13 +28,25 @@ If the name of the parameter is different than the name of the attribute or scop
|
|
28
28
|
filter :status, name: :current_status
|
29
29
|
```
|
30
30
|
|
31
|
+
This option can also be helpful with nested filters so that the query parameter can be prefixed with the model name. See the `association` option for an example.
|
32
|
+
|
31
33
|
#### association
|
32
|
-
If the attribute or scope is nested, it can be referenced by naming the association.
|
34
|
+
If the attribute or scope is nested, it can be referenced by naming the association. For example, if the manager_id attribute lives on an employee's department record, use the following:
|
33
35
|
|
34
36
|
```ruby
|
35
37
|
filter :manager_id, association: :department
|
36
38
|
```
|
37
39
|
|
40
|
+
The attribute or scope can be nested more than one level. Declare the filter with an array specifying the associations in order. For example, if an employee belongs to a department and a department belongs to a business unit, use the following to query on the business unit name:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
filter :business_unit_name, name: :name, association: [:department, :business_unit]
|
44
|
+
```
|
45
|
+
|
46
|
+
If an association is a `has_many` [the distinct method](https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-distinct) is called on the query.
|
47
|
+
|
48
|
+
_Limitation:_ If there is more than one association to the same table _and_ both associations can be part of the query, then you cannot use a nested filter directly. Instead, build a scope that disambiguates the associations then build a filter against that scope.
|
49
|
+
|
38
50
|
#### validates
|
39
51
|
If the filter value should be validated, use the `validates` option along with [ActiveModel validations](https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). Here's an example of the inclusion validator being used to restrict sizes:
|
40
52
|
|
@@ -85,39 +97,9 @@ filter :sale_price, range: :max_only
|
|
85
97
|
|
86
98
|
In the first example, query parameters could include <tt>price</tt>, <tt>price_min</tt>, and <tt>price_max</tt>.
|
87
99
|
|
88
|
-
### Query Classes
|
89
|
-
|
90
|
-
Include module `Filterameter::DeclarativeFilters` in the query class. The model must be declared using `model`, and a default query can optionally be declared using `default_query`. If no default query is provided, then the default is `.all`.
|
91
|
-
|
92
|
-
#### Example
|
93
|
-
|
94
|
-
Here's what a query class for the Widgets model with filters on size and color might look like:
|
95
|
-
|
96
|
-
```ruby
|
97
|
-
class WidgetQuery
|
98
|
-
include Filterameter::DeclarativeFilters
|
99
|
-
|
100
|
-
model Widget
|
101
|
-
filter :size
|
102
|
-
filter :color
|
103
|
-
end
|
104
|
-
```
|
105
|
-
|
106
|
-
Build the query using class method `build_query`. The method takes two parameters:
|
107
|
-
|
108
|
-
- filter: the hash of filter parameters
|
109
|
-
- starting_query: any scope to build on (if not provided, the default query is the starting point)
|
110
|
-
|
111
|
-
Here's how the query might be invoked:
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
filters = { size: 'large', color: 'blue' }
|
115
|
-
widgets = WidgetQuery.build_query(filters, Widget.limit(10))
|
116
|
-
```
|
117
|
-
|
118
100
|
### Controllers
|
119
101
|
|
120
|
-
Include module `Filterameter::
|
102
|
+
Include module `Filterameter::DeclarativeFilters` in the controller. Add before action callback `build_filtered_query` for controller actions that should build the query.
|
121
103
|
|
122
104
|
Rails conventions are used to determine the controller's model as well as the name of the instance variable to apply the filters to. For example, the PhotosController will use the variable `@photos` to store a query against the Photo model. **If the conventions do not provide the correct info**, they can be overridden with the following two methods:
|
123
105
|
|
@@ -141,7 +123,7 @@ In the happy path, the WidgetsController serves Widgets and can filter on size a
|
|
141
123
|
|
142
124
|
```ruby
|
143
125
|
class WidgetController < ApplicationController
|
144
|
-
include Filterameter::
|
126
|
+
include Filterameter::DeclarativeFilters
|
145
127
|
before_action :build_filtered_query, only: :index
|
146
128
|
|
147
129
|
filter :size
|
@@ -1,27 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Filterameter
|
4
|
-
# = Declarative Filters
|
4
|
+
# = Declarative Controller Filters
|
5
5
|
#
|
6
|
-
# Mixin DeclarativeFilters
|
6
|
+
# Mixin DeclarativeFilters can included in controllers to enable the filter DSL.
|
7
7
|
module DeclarativeFilters
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
include Filterameter::Filterable
|
10
10
|
|
11
11
|
class_methods do
|
12
|
-
|
13
|
-
|
14
|
-
def model(model_class)
|
12
|
+
def filter_model(model_class, query_var_name = nil)
|
15
13
|
filter_coordinator.model_class = model_class
|
14
|
+
filter_query_var_name(query_var_name) if query_var_name.present?
|
16
15
|
end
|
17
16
|
|
18
|
-
def
|
19
|
-
filter_coordinator.
|
17
|
+
def filter_query_var_name(query_variable_name)
|
18
|
+
filter_coordinator.query_variable_name = query_variable_name
|
20
19
|
end
|
21
20
|
|
22
21
|
def filter_coordinator
|
23
|
-
@filter_coordinator ||= Filterameter::
|
22
|
+
@filter_coordinator ||= Filterameter::FilterCoordinator.new(controller_name, controller_path)
|
24
23
|
end
|
25
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build_filtered_query
|
29
|
+
var_name = "@#{self.class.filter_coordinator.query_variable_name}"
|
30
|
+
instance_variable_set(
|
31
|
+
var_name,
|
32
|
+
self.class.filter_coordinator.build_query(params.to_unsafe_h.fetch(:filter, {}),
|
33
|
+
instance_variable_get(var_name))
|
34
|
+
)
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/inflector'
|
4
|
+
|
5
|
+
require 'active_support/rails'
|
6
|
+
require 'action_dispatch'
|
7
|
+
require 'action_controller/metal/live'
|
8
|
+
require 'action_controller/metal/strong_parameters'
|
9
|
+
|
10
|
+
module Filterameter
|
11
|
+
# = Filter Coordinator
|
12
|
+
#
|
13
|
+
# Class FilterCoordinator stores the configuration declared via class-level method calls such as the list of
|
14
|
+
# filters and the optionally declared model class. Each controller will have one instance of the coordinator
|
15
|
+
# stored as a class variable.
|
16
|
+
#
|
17
|
+
# The coordinators encapsulate references to the Query Builder and Filter Registry to keep the namespace clean for
|
18
|
+
# controllers that implement filter parameters.
|
19
|
+
class FilterCoordinator
|
20
|
+
attr_writer :query_variable_name
|
21
|
+
|
22
|
+
delegate :add_filter, to: :registry
|
23
|
+
delegate :build_query, to: :query_builder
|
24
|
+
|
25
|
+
def initialize(controller_name, controller_path)
|
26
|
+
@controller_name = controller_name
|
27
|
+
@controller_path = controller_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def model_class=(model_class)
|
31
|
+
@model_class = model_class.is_a?(String) ? model_class.constantize : model_class
|
32
|
+
end
|
33
|
+
|
34
|
+
def query_builder
|
35
|
+
@query_builder ||= Filterameter::QueryBuilder.new(default_query, registry)
|
36
|
+
end
|
37
|
+
|
38
|
+
def query_variable_name
|
39
|
+
@query_variable_name ||= model_class.model_name.plural
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def model_class
|
45
|
+
@model_class ||= @controller_name.classify.safe_constantize ||
|
46
|
+
@controller_path.classify.safe_constantize ||
|
47
|
+
raise(Filterameter::Exceptions::CannotDetermineModelError.new(@controller_name,
|
48
|
+
@controller_path))
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_query
|
52
|
+
model_class.all
|
53
|
+
end
|
54
|
+
|
55
|
+
# lazy so that model_class can be optionally set
|
56
|
+
def registry
|
57
|
+
@registry ||= Filterameter::FilterRegistry.new(Filterameter::FilterFactory.new(model_class))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -16,7 +16,7 @@ module Filterameter
|
|
16
16
|
|
17
17
|
validate_options(options)
|
18
18
|
@name = options.fetch(:name, parameter_name).to_s
|
19
|
-
@association = options[:association]
|
19
|
+
@association = Array.wrap(options[:association]).presence
|
20
20
|
@filter_on_empty = options.fetch(:filter_on_empty, false)
|
21
21
|
@validations = Array.wrap(options[:validates])
|
22
22
|
@raw_partial_options = options.fetch(:partial, false)
|
@@ -24,7 +24,7 @@ module Filterameter
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def nested?
|
27
|
-
|
27
|
+
!@association.nil?
|
28
28
|
end
|
29
29
|
|
30
30
|
def validations?
|
@@ -10,14 +10,23 @@ module Filterameter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def build(declaration)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
if declaration.nested?
|
14
|
+
build_nested_filter(declaration)
|
15
|
+
else
|
16
|
+
build_filter(@model_class, declaration)
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
20
21
|
|
22
|
+
def build_nested_filter(declaration)
|
23
|
+
model = model_from_association(declaration.association)
|
24
|
+
filter = build_filter(model, declaration)
|
25
|
+
clazz = filter_class(declaration.association)
|
26
|
+
|
27
|
+
clazz.new(declaration.association, model, filter)
|
28
|
+
end
|
29
|
+
|
21
30
|
def build_filter(model, declaration) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
22
31
|
# checking dangerous_class_method? excludes any names that cannot be scope names, such as "name"
|
23
32
|
if model.respond_to?(declaration.name) && !model.dangerous_class_method?(declaration.name)
|
@@ -33,9 +42,28 @@ module Filterameter
|
|
33
42
|
end
|
34
43
|
end
|
35
44
|
|
45
|
+
def filter_class(association_names)
|
46
|
+
if any_collections?(association_names)
|
47
|
+
Filters::NestedCollectionFilter
|
48
|
+
else
|
49
|
+
Filters::NestedFilter
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def any_collections?(association_names)
|
54
|
+
association_names.reduce(@model_class) do |model, name|
|
55
|
+
association = model.reflect_on_association(name)
|
56
|
+
return true if association.collection?
|
57
|
+
|
58
|
+
association.klass
|
59
|
+
end
|
60
|
+
|
61
|
+
false
|
62
|
+
end
|
63
|
+
|
36
64
|
# TODO: rescue then raise custom error with cause
|
37
65
|
def model_from_association(association)
|
38
|
-
|
66
|
+
association.flatten.reduce(@model_class) { |memo, name| memo.reflect_on_association(name).klass }
|
39
67
|
# rescue StandardError => e
|
40
68
|
end
|
41
69
|
end
|
@@ -51,8 +51,8 @@ module Filterameter
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def add_range_maximum(parameter_name, options)
|
54
|
-
|
55
|
-
@declarations[
|
54
|
+
parameter_name_max = "#{parameter_name}_max"
|
55
|
+
@declarations[parameter_name_max] = Filterameter::FilterDeclaration.new(parameter_name_max,
|
56
56
|
options.merge(range: :max_only))
|
57
57
|
end
|
58
58
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Filterameter
|
4
|
+
module Filters
|
5
|
+
# = Nested Collection Filter
|
6
|
+
#
|
7
|
+
# Class NestedCollectionFilter joins the nested table(s), merges the filter to the association's model, then makes
|
8
|
+
# the results distinct.
|
9
|
+
class NestedCollectionFilter < NestedFilter
|
10
|
+
def apply(*)
|
11
|
+
super.distinct
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,8 +6,8 @@ module Filterameter
|
|
6
6
|
#
|
7
7
|
# Class NestedFilter joins the nested table(s) then merges the filter to the association's model.
|
8
8
|
class NestedFilter
|
9
|
-
def initialize(
|
10
|
-
@joins_values =
|
9
|
+
def initialize(association_names, association_model, attribute_filter)
|
10
|
+
@joins_values = build_joins_values_argument(association_names)
|
11
11
|
@association_model = association_model
|
12
12
|
@attribute_filter = attribute_filter
|
13
13
|
end
|
@@ -16,6 +16,20 @@ module Filterameter
|
|
16
16
|
query.joins(@joins_values)
|
17
17
|
.merge(@attribute_filter.apply(@association_model, value))
|
18
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_joins_values_argument(association_names)
|
23
|
+
return association_names.first if association_names.size == 1
|
24
|
+
|
25
|
+
convert_to_nested_hash(association_names)
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_to_nested_hash(association_names)
|
29
|
+
{}.tap do |nested_hash|
|
30
|
+
association_names.reduce(nested_hash) { |memo, name| memo.store(name, {}) }
|
31
|
+
end
|
32
|
+
end
|
19
33
|
end
|
20
34
|
end
|
21
35
|
end
|
data/lib/filterameter/version.rb
CHANGED
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Kummer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: '1.64'
|
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.64'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rubocop-packaging
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 2.
|
145
|
+
version: '2.25'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 2.
|
152
|
+
version: '2.25'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: simplecov
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,7 +164,8 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0.18'
|
167
|
-
description:
|
167
|
+
description: Declare filters in Rails controllers to increase readability and reduce
|
168
|
+
boilerplate code.
|
168
169
|
email:
|
169
170
|
- todd@rockridgesolutions.com
|
170
171
|
executables: []
|
@@ -175,15 +176,12 @@ files:
|
|
175
176
|
- Rakefile
|
176
177
|
- lib/filterameter.rb
|
177
178
|
- lib/filterameter/configuration.rb
|
178
|
-
- lib/filterameter/coordinators/base.rb
|
179
|
-
- lib/filterameter/coordinators/controller_coordinator.rb
|
180
|
-
- lib/filterameter/coordinators/query_coordinator.rb
|
181
|
-
- lib/filterameter/declarative_controller_filters.rb
|
182
179
|
- lib/filterameter/declarative_filters.rb
|
183
180
|
- lib/filterameter/exceptions.rb
|
184
181
|
- lib/filterameter/exceptions/cannot_determine_model_error.rb
|
185
182
|
- lib/filterameter/exceptions/undeclared_parameter_error.rb
|
186
183
|
- lib/filterameter/exceptions/validation_error.rb
|
184
|
+
- lib/filterameter/filter_coordinator.rb
|
187
185
|
- lib/filterameter/filter_declaration.rb
|
188
186
|
- lib/filterameter/filter_factory.rb
|
189
187
|
- lib/filterameter/filter_registry.rb
|
@@ -194,6 +192,7 @@ files:
|
|
194
192
|
- lib/filterameter/filters/matches_filter.rb
|
195
193
|
- lib/filterameter/filters/maximum_filter.rb
|
196
194
|
- lib/filterameter/filters/minimum_filter.rb
|
195
|
+
- lib/filterameter/filters/nested_collection_filter.rb
|
197
196
|
- lib/filterameter/filters/nested_filter.rb
|
198
197
|
- lib/filterameter/filters/scope_filter.rb
|
199
198
|
- lib/filterameter/log_subscriber.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Filterameter
|
4
|
-
module Coordinators
|
5
|
-
# = Coordinators Base
|
6
|
-
#
|
7
|
-
# The main responsibility of the Coordinators classes is to keep the namespace clean for controllers and query
|
8
|
-
# objects that implement filter parameters. The coordinators encapsulate references to the Query Builder and
|
9
|
-
# Filter Registry.
|
10
|
-
class Base
|
11
|
-
attr_reader :model_class
|
12
|
-
|
13
|
-
delegate :add_filter, to: :registry
|
14
|
-
delegate :build_query, to: :query_builder
|
15
|
-
|
16
|
-
def model_class=(model_class)
|
17
|
-
@model_class = model_class.is_a?(String) ? model_class.constantize : model_class
|
18
|
-
end
|
19
|
-
|
20
|
-
def query_builder
|
21
|
-
@query_builder ||= Filterameter::QueryBuilder.new(default_query, registry)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def default_query
|
27
|
-
model_class.all
|
28
|
-
end
|
29
|
-
|
30
|
-
# lazy so that model_class can be optionally set
|
31
|
-
def registry
|
32
|
-
@registry ||= Filterameter::FilterRegistry.new(Filterameter::FilterFactory.new(model_class))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/inflector'
|
4
|
-
|
5
|
-
require 'active_support/rails'
|
6
|
-
require 'action_dispatch'
|
7
|
-
require 'action_controller/metal/live'
|
8
|
-
require 'action_controller/metal/strong_parameters'
|
9
|
-
|
10
|
-
module Filterameter
|
11
|
-
module Coordinators
|
12
|
-
# = Controller Filters
|
13
|
-
#
|
14
|
-
# Class ControllerFilters stores the configuration declared via class-level method calls such as the list of
|
15
|
-
# filters and the optionally declared model class. Each controller will have one instance of the controller
|
16
|
-
# declarations stored as a class variable.
|
17
|
-
class ControllerCoordinator < Filterameter::Coordinators::Base
|
18
|
-
attr_writer :query_variable_name
|
19
|
-
|
20
|
-
def initialize(controller_name, controller_path)
|
21
|
-
@controller_name = controller_name
|
22
|
-
@controller_path = controller_path
|
23
|
-
super()
|
24
|
-
end
|
25
|
-
|
26
|
-
def query_variable_name
|
27
|
-
@query_variable_name ||= model_class.model_name.plural
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def model_class
|
33
|
-
@model_class ||= @controller_name.classify.safe_constantize ||
|
34
|
-
@controller_path.classify.safe_constantize ||
|
35
|
-
raise(Filterameter::Exceptions::CannotDetermineModelError.new(@controller_name,
|
36
|
-
@controller_path))
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Filterameter
|
4
|
-
module Coordinators
|
5
|
-
# = Query Coordinator
|
6
|
-
#
|
7
|
-
# Class QueryCoordinator coordinates the filter logic for query classes.
|
8
|
-
class QueryCoordinator < Filterameter::Coordinators::Base
|
9
|
-
attr_writer :default_query
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def default_query
|
14
|
-
@default_query || super
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Filterameter
|
4
|
-
# = Declarative Controller Filters
|
5
|
-
#
|
6
|
-
# Mixin DeclarativeControllerFilters can included in controllers to enable the filter DSL.
|
7
|
-
module DeclarativeControllerFilters
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
include Filterameter::Filterable
|
10
|
-
|
11
|
-
class_methods do
|
12
|
-
def filter_model(model_class, query_var_name = nil)
|
13
|
-
filter_coordinator.model_class = model_class
|
14
|
-
filter_query_var_name(query_var_name) if query_var_name.present?
|
15
|
-
end
|
16
|
-
|
17
|
-
def filter_query_var_name(query_variable_name)
|
18
|
-
filter_coordinator.query_variable_name = query_variable_name
|
19
|
-
end
|
20
|
-
|
21
|
-
def filter_coordinator
|
22
|
-
@filter_coordinator ||= Filterameter::Coordinators::ControllerCoordinator.new(controller_name, controller_path)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def build_filtered_query
|
29
|
-
var_name = "@#{self.class.filter_coordinator.query_variable_name}"
|
30
|
-
instance_variable_set(
|
31
|
-
var_name,
|
32
|
-
self.class.filter_coordinator.build_query(params.to_unsafe_h.fetch(:filter, {}),
|
33
|
-
instance_variable_get(var_name))
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|