kiroshi 0.1.0 → 0.2.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 +4 -4
- data/.rubocop_todo.yml +4 -8
- data/README.md +56 -41
- data/lib/kiroshi/filter.rb +57 -41
- data/lib/kiroshi/filter_query/exact.rb +38 -0
- data/lib/kiroshi/filter_query/like.rb +42 -0
- data/lib/kiroshi/filter_query.rb +127 -0
- data/lib/kiroshi/filter_runner.rb +164 -0
- data/lib/kiroshi/filters/class_methods.rb +169 -0
- data/lib/kiroshi/filters.rb +68 -62
- data/lib/kiroshi/version.rb +1 -1
- data/lib/kiroshi.rb +138 -3
- data/spec/lib/kiroshi/filter_query/exact_spec.rb +274 -0
- data/spec/lib/kiroshi/filter_query/like_spec.rb +271 -0
- data/spec/lib/kiroshi/filter_query_spec.rb +39 -0
- data/spec/lib/kiroshi/filter_runner_spec.rb +94 -0
- data/spec/lib/kiroshi/filter_spec.rb +9 -12
- data/spec/lib/kiroshi/filters/class_methods_spec.rb +59 -0
- data/spec/lib/kiroshi/filters_spec.rb +165 -6
- data/spec/support/db/schema.rb +14 -0
- data/spec/support/factories/tag.rb +7 -0
- data/spec/support/models/document.rb +2 -0
- data/spec/support/models/tag.rb +7 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff66735688ded970094d5a88a9bcd67ad4f9cac7679fc55ceb75534d9b16d9fc
|
4
|
+
data.tar.gz: d6da2da4ec294c0d134ceff028e19b30fa5e13ddab2fae2ad0582a5fdfc559aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15f142b43b0fcd7fc12f8cd2c1246031aabec104deaf1270030eca5afa56d5776d5c3fec301422c12baec0c531d5366f39832b4afe6ec3d1c83f40ce3e94aea5
|
7
|
+
data.tar.gz: af94b97459b7a157c6ea30f36c36b937e9a75c25b7081106cf6b6d104b3514687a7da4842e9ac847b7669954bab65f707e8a609d55e3666393f6da09cad6d9c4
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2025-08-
|
3
|
+
# on 2025-08-18 22:27:27 UTC using RuboCop version 1.79.2.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -13,11 +13,7 @@ RSpec/NoExpectationExample:
|
|
13
13
|
Exclude:
|
14
14
|
- 'spec/lib/kiroshi_spec.rb'
|
15
15
|
|
16
|
-
# Offense count:
|
17
|
-
|
18
|
-
Style/Documentation:
|
16
|
+
# Offense count: 1
|
17
|
+
RSpec/PendingWithoutReason:
|
19
18
|
Exclude:
|
20
|
-
- 'spec
|
21
|
-
- 'test/**/*'
|
22
|
-
- 'lib/kiroshi/filter.rb'
|
23
|
-
- 'lib/kiroshi/filters.rb'
|
19
|
+
- 'spec/lib/kiroshi/filters_spec.rb'
|
data/README.md
CHANGED
@@ -7,16 +7,16 @@
|
|
7
7
|
|
8
8
|
## Yard Documentation
|
9
9
|
|
10
|
-
[https://www.rubydoc.info/gems/kiroshi/0.
|
10
|
+
[https://www.rubydoc.info/gems/kiroshi/0.2.0](https://www.rubydoc.info/gems/kiroshi/0.2.0)
|
11
11
|
|
12
12
|
Kiroshi has been designed to make filtering ActiveRecord queries easier
|
13
13
|
by providing a flexible and reusable filtering system. It allows you to
|
14
14
|
define filter sets that can be applied to any ActiveRecord scope,
|
15
15
|
supporting both exact matches and partial matching using SQL LIKE operations.
|
16
16
|
|
17
|
-
Current Release: [0.
|
17
|
+
Current Release: [0.2.0](https://github.com/darthjee/kiroshi/tree/0.2.0)
|
18
18
|
|
19
|
-
[Next release](https://github.com/darthjee/kiroshi/compare/0.
|
19
|
+
[Next release](https://github.com/darthjee/kiroshi/compare/0.2.0...master)
|
20
20
|
|
21
21
|
## Installation
|
22
22
|
|
@@ -100,6 +100,7 @@ products = filters.apply(Product.all)
|
|
100
100
|
##### Controller Integration
|
101
101
|
|
102
102
|
```ruby
|
103
|
+
# URL: /documents?filter[name]=report&filter[status]=published&filter[author]=john
|
103
104
|
class DocumentsController < ApplicationController
|
104
105
|
def index
|
105
106
|
@documents = document_filters.apply(Document.all)
|
@@ -113,7 +114,7 @@ class DocumentsController < ApplicationController
|
|
113
114
|
end
|
114
115
|
|
115
116
|
def filter_params
|
116
|
-
params
|
117
|
+
params[:filter]&.permit(:name, :status, :category, :author)
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
@@ -128,6 +129,7 @@ end
|
|
128
129
|
##### Nested Resource Filtering
|
129
130
|
|
130
131
|
```ruby
|
132
|
+
# URL: /users/123/articles?filter[title]=ruby&filter[published]=true&filter[tag]=tutorial
|
131
133
|
class ArticleFilters < Kiroshi::Filters
|
132
134
|
filter_by :title, match: :like
|
133
135
|
filter_by :published
|
@@ -141,54 +143,67 @@ def articles
|
|
141
143
|
end
|
142
144
|
|
143
145
|
def article_filters
|
144
|
-
ArticleFilters.new(params
|
146
|
+
ArticleFilters.new(params[:filter]&.permit(:title, :published, :tag))
|
145
147
|
end
|
146
148
|
```
|
147
149
|
|
148
|
-
|
150
|
+
##### Joined Tables and Table Qualification
|
149
151
|
|
150
|
-
|
151
|
-
is the individual filter class that applies filtering logic to ActiveRecord scopes.
|
152
|
-
It's automatically used by `Kiroshi::Filters`, but can also be used standalone.
|
153
|
-
|
154
|
-
#### Standalone Usage
|
152
|
+
When working with joined tables that have columns with the same name, you can specify which table to filter on using the `table` parameter:
|
155
153
|
|
156
154
|
```ruby
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
#
|
162
|
-
|
163
|
-
scope = name_filter.apply(scope, { name: 'report' })
|
164
|
-
scope = status_filter.apply(scope, { status: 'published' })
|
165
|
-
```
|
155
|
+
class DocumentFilters < Kiroshi::Filters
|
156
|
+
filter_by :name, match: :like # Filters by documents.name (default table)
|
157
|
+
filter_by :tag_name, match: :like, table: :tags # Filters by tags.name
|
158
|
+
filter_by :status # Filters by documents.status
|
159
|
+
filter_by :category, table: :documents # Explicitly filter by documents.category
|
160
|
+
end
|
166
161
|
|
167
|
-
|
162
|
+
# Example with joined scope
|
163
|
+
scope = Document.joins(:tags)
|
164
|
+
filters = DocumentFilters.new(tag_name: 'ruby', status: 'published')
|
165
|
+
filtered_documents = filters.apply(scope)
|
166
|
+
# Generates: WHERE tags.name LIKE '%ruby%' AND documents.status = 'published'
|
167
|
+
```
|
168
168
|
|
169
|
-
|
170
|
-
- `match: :like` - Performs partial matching using SQL LIKE
|
169
|
+
###### Table Qualification Examples
|
171
170
|
|
172
171
|
```ruby
|
173
|
-
#
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
172
|
+
# Filter documents by tag name and document status
|
173
|
+
class DocumentTagFilters < Kiroshi::Filters
|
174
|
+
filter_by :tag_name, match: :like, table: :tags # Search in tags.name
|
175
|
+
filter_by :status, table: :documents # Search in documents.status
|
176
|
+
filter_by :title, match: :like # Search in documents.title (default table)
|
177
|
+
end
|
178
|
+
|
179
|
+
scope = Document.joins(:tags)
|
180
|
+
filters = DocumentTagFilters.new(tag_name: 'programming', status: 'published', title: 'Ruby')
|
181
|
+
result = filters.apply(scope)
|
182
|
+
# Generates: WHERE tags.name LIKE '%programming%' AND documents.status = 'published' AND documents.title LIKE '%Ruby%'
|
183
|
+
|
184
|
+
# Filter by both document and tag attributes with different field names
|
185
|
+
class AdvancedDocumentFilters < Kiroshi::Filters
|
186
|
+
filter_by :title, match: :like, table: :documents
|
187
|
+
filter_by :tag_name, match: :like, table: :tags
|
188
|
+
filter_by :category, table: :documents
|
189
|
+
filter_by :tag_color, table: :tags
|
190
|
+
end
|
191
|
+
|
192
|
+
scope = Document.joins(:tags)
|
193
|
+
filters = AdvancedDocumentFilters.new(
|
194
|
+
title: 'Ruby',
|
195
|
+
tag_name: 'tutorial',
|
196
|
+
category: 'programming',
|
197
|
+
tag_color: 'blue'
|
198
|
+
)
|
199
|
+
result = filters.apply(scope)
|
200
|
+
# Generates: WHERE documents.title LIKE '%Ruby%' AND tags.name LIKE '%tutorial%' AND documents.category = 'programming' AND tags.color = 'blue'
|
182
201
|
```
|
183
202
|
|
184
|
-
|
203
|
+
The `table` parameter accepts both symbols and strings, and helps resolve column name ambiguity in complex joined queries.
|
185
204
|
|
186
|
-
|
205
|
+
## API Reference
|
187
206
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
filter.apply(Document.all, { name: '' }) # Returns original scope
|
192
|
-
filter.apply(Document.all, {}) # Returns original scope
|
193
|
-
filter.apply(Document.all, { name: 'value' }) # Applies filter
|
194
|
-
```
|
207
|
+
Kiroshi provides a simple, clean API focused on the `Kiroshi::Filters` class. Individual filters are handled internally and don't require direct interaction in most use cases.
|
208
|
+
|
209
|
+
For detailed API documentation, see the [YARD documentation](https://www.rubydoc.info/gems/kiroshi/0.2.0).
|
data/lib/kiroshi/filter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Kiroshi
|
4
|
+
# @api private
|
4
5
|
# @author darthjee
|
5
6
|
#
|
6
7
|
# A filter class that applies filtering logic to ActiveRecord scopes
|
@@ -10,18 +11,46 @@ module Kiroshi
|
|
10
11
|
#
|
11
12
|
# @example Creating and applying an exact filter
|
12
13
|
# filter = Kiroshi::Filter.new(:name)
|
13
|
-
# filtered_scope = filter.apply(Document.all,
|
14
|
+
# filtered_scope = filter.apply(scope: Document.all, value: 'John')
|
14
15
|
#
|
15
16
|
# @example Creating and applying a LIKE filter
|
16
17
|
# filter = Kiroshi::Filter.new(:title, match: :like)
|
17
|
-
# filtered_scope = filter.apply(Article.all,
|
18
|
+
# filtered_scope = filter.apply(scope: Article.all, value: 'Ruby')
|
19
|
+
#
|
20
|
+
# @example Creating and applying a filter with specific value
|
21
|
+
# filter = Kiroshi::Filter.new(:status)
|
22
|
+
# filtered_scope = filter.apply(scope: Document.all, value: 'published')
|
18
23
|
#
|
19
24
|
# @since 0.1.0
|
20
25
|
class Filter
|
26
|
+
attr_reader :attribute, :match, :table_name
|
27
|
+
|
28
|
+
# @!method attribute
|
29
|
+
# @api private
|
30
|
+
#
|
31
|
+
# Returns the attribute name to filter by
|
32
|
+
#
|
33
|
+
# @return [Symbol] the attribute name to filter by
|
34
|
+
|
35
|
+
# @!method match
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
# Returns the matching type (+:exact+ or +:like+)
|
39
|
+
#
|
40
|
+
# @return [Symbol] the matching type (+:exact+ or +:like+)
|
41
|
+
|
42
|
+
# @!method table_name
|
43
|
+
# @api private
|
44
|
+
#
|
45
|
+
# Returns the table name to qualify the attribute
|
46
|
+
#
|
47
|
+
# @return [String, String, nil] the table name or nil if not specified
|
48
|
+
|
21
49
|
# Creates a new Filter instance
|
22
50
|
#
|
23
51
|
# @param attribute [Symbol] the attribute name to filter by
|
24
52
|
# @param match [Symbol] the matching type, defaults to :exact
|
53
|
+
# @param table [String, Symbol, nil] the table name to qualify the attribute, defaults to nil
|
25
54
|
# @option match [Symbol] :exact performs exact matching (default)
|
26
55
|
# @option match [Symbol] :like performs partial matching using SQL LIKE
|
27
56
|
#
|
@@ -31,69 +60,56 @@ module Kiroshi
|
|
31
60
|
# @example Creating a partial match filter
|
32
61
|
# filter = Kiroshi::Filter.new(:name, match: :like)
|
33
62
|
#
|
63
|
+
# @example Creating a filter with table qualification
|
64
|
+
# filter = Kiroshi::Filter.new(:name, table: 'documents')
|
65
|
+
#
|
34
66
|
# @since 0.1.0
|
35
|
-
def initialize(attribute, match: :exact)
|
67
|
+
def initialize(attribute, match: :exact, table: nil)
|
36
68
|
@attribute = attribute
|
37
69
|
@match = match
|
70
|
+
@table_name = table
|
38
71
|
end
|
39
72
|
|
40
73
|
# Applies the filter to the given scope
|
41
74
|
#
|
42
|
-
# This method
|
43
|
-
#
|
44
|
-
#
|
75
|
+
# This method applies the appropriate WHERE clause to the scope using the
|
76
|
+
# provided value. If no value is present or the value is blank, the original
|
77
|
+
# scope is returned unchanged.
|
45
78
|
#
|
46
79
|
# @param scope [ActiveRecord::Relation] the ActiveRecord scope to filter
|
47
|
-
# @param
|
80
|
+
# @param value [Object, nil] the value to use for filtering, defaults to nil
|
48
81
|
#
|
49
82
|
# @return [ActiveRecord::Relation] the filtered scope
|
50
83
|
#
|
51
84
|
# @example Applying an exact filter
|
52
85
|
# filter = Kiroshi::Filter.new(:status)
|
53
|
-
# filter.apply(Document.all,
|
86
|
+
# filter.apply(scope: Document.all, value: 'published')
|
54
87
|
# # Generates: WHERE status = 'published'
|
55
88
|
#
|
56
89
|
# @example Applying a LIKE filter
|
57
90
|
# filter = Kiroshi::Filter.new(:title, match: :like)
|
58
|
-
# filter.apply(Article.all,
|
91
|
+
# filter.apply(scope: Article.all, value: 'Ruby')
|
59
92
|
# # Generates: WHERE title LIKE '%Ruby%'
|
60
93
|
#
|
94
|
+
# @example Applying a filter with table qualification
|
95
|
+
# filter = Kiroshi::Filter.new(:name, table: 'documents')
|
96
|
+
# filter.apply(scope: Document.joins(:tags), value: 'report')
|
97
|
+
# # Generates: WHERE documents.name = 'report'
|
98
|
+
#
|
99
|
+
# @example Applying a filter with table qualification for tags
|
100
|
+
# filter = Kiroshi::Filter.new(:name, table: 'tags')
|
101
|
+
# filter.apply(scope: Document.joins(:tags), value: 'ruby')
|
102
|
+
# # Generates: WHERE tags.name = 'ruby'
|
103
|
+
#
|
61
104
|
# @example With empty filter value
|
62
105
|
# filter = Kiroshi::Filter.new(:name)
|
63
|
-
# filter.apply(User.all,
|
106
|
+
# filter.apply(scope: User.all, value: nil)
|
64
107
|
# # Returns the original scope unchanged
|
65
108
|
#
|
66
|
-
# @since 0.
|
67
|
-
def apply(scope
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
case match
|
72
|
-
when :like
|
73
|
-
scope.where("#{attribute} LIKE ?", "%#{filter_value}%")
|
74
|
-
else # :exact (default)
|
75
|
-
scope.where(attribute => filter_value)
|
76
|
-
end
|
109
|
+
# @since 0.2.0
|
110
|
+
def apply(scope:, value: nil)
|
111
|
+
runner = FilterRunner.new(filter: self, scope: scope, value: value)
|
112
|
+
runner.apply
|
77
113
|
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
attr_reader :attribute, :match
|
82
|
-
|
83
|
-
# @!method attribute
|
84
|
-
# @api private
|
85
|
-
# @private
|
86
|
-
#
|
87
|
-
# Returns the attribute name to filter by
|
88
|
-
#
|
89
|
-
# @return [Symbol] the attribute name to filter by
|
90
|
-
|
91
|
-
# @!method match
|
92
|
-
# @api private
|
93
|
-
# @private
|
94
|
-
#
|
95
|
-
# Returns the matching type (+:exact+ or +:like+)
|
96
|
-
#
|
97
|
-
# @return [Symbol] the matching type (+:exact+ or +:like+)
|
98
114
|
end
|
99
115
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kiroshi
|
4
|
+
class FilterQuery
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Query strategy for exact matching
|
9
|
+
#
|
10
|
+
# This class implements the exact match query strategy, generating
|
11
|
+
# WHERE clauses with exact equality comparisons.
|
12
|
+
#
|
13
|
+
# @example Applying exact match query
|
14
|
+
# query = Kiroshi::FilterQuery::Exact.new(filter_runner)
|
15
|
+
# query.apply
|
16
|
+
# # Generates: WHERE attribute = 'value'
|
17
|
+
#
|
18
|
+
# @since 0.1.1
|
19
|
+
class Exact < FilterQuery
|
20
|
+
# Applies exact match filtering to the scope
|
21
|
+
#
|
22
|
+
# This method generates a WHERE clause with exact equality matching
|
23
|
+
# for the filter's attribute and value.
|
24
|
+
#
|
25
|
+
# @return [ActiveRecord::Relation] the filtered scope with exact match
|
26
|
+
#
|
27
|
+
# @example Applying exact match
|
28
|
+
# query = Exact.new(filter_runner)
|
29
|
+
# query.apply
|
30
|
+
# # Generates: WHERE status = 'published'
|
31
|
+
#
|
32
|
+
# @since 0.1.1
|
33
|
+
def apply
|
34
|
+
scope.where(table_name => { attribute => value })
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kiroshi
|
4
|
+
class FilterQuery
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Query strategy for LIKE matching
|
9
|
+
#
|
10
|
+
# This class implements the LIKE match query strategy, generating
|
11
|
+
# WHERE clauses with SQL LIKE operations for partial matching.
|
12
|
+
#
|
13
|
+
# @example Applying LIKE match query
|
14
|
+
# query = Kiroshi::FilterQuery::Like.new(filter_runner)
|
15
|
+
# query.apply
|
16
|
+
# # Generates: WHERE table_name.attribute LIKE '%value%'
|
17
|
+
#
|
18
|
+
# @since 0.1.1
|
19
|
+
class Like < FilterQuery
|
20
|
+
# Applies LIKE match filtering to the scope
|
21
|
+
#
|
22
|
+
# This method generates a WHERE clause with SQL LIKE operation
|
23
|
+
# for partial matching, including table name prefix to avoid
|
24
|
+
# column ambiguity in complex queries.
|
25
|
+
#
|
26
|
+
# @return [ActiveRecord::Relation] the filtered scope with LIKE match
|
27
|
+
#
|
28
|
+
# @example Applying LIKE match
|
29
|
+
# query = Like.new(filter_runner)
|
30
|
+
# query.apply
|
31
|
+
# # Generates: WHERE documents.name LIKE '%ruby%'
|
32
|
+
#
|
33
|
+
# @since 0.1.1
|
34
|
+
def apply
|
35
|
+
scope.where(
|
36
|
+
"#{table_name}.#{attribute} LIKE ?",
|
37
|
+
"%#{value}%"
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kiroshi
|
4
|
+
# @api private
|
5
|
+
# @author darthjee
|
6
|
+
#
|
7
|
+
# Factory class for creating filter query strategies
|
8
|
+
#
|
9
|
+
# This class implements the Strategy pattern for handling different types of
|
10
|
+
# database queries based on the filter match type. It provides a factory method
|
11
|
+
# to create the appropriate query strategy class.
|
12
|
+
#
|
13
|
+
# @example Getting an exact match query strategy
|
14
|
+
# query = Kiroshi::FilterQuery.for(:exact).new(filter_runner)
|
15
|
+
# query.apply
|
16
|
+
#
|
17
|
+
# @example Getting a LIKE match query strategy
|
18
|
+
# query = Kiroshi::FilterQuery.for(:like).new(filter_runner)
|
19
|
+
# query.apply
|
20
|
+
#
|
21
|
+
# @since 0.1.1
|
22
|
+
class FilterQuery
|
23
|
+
autoload :Exact, 'kiroshi/filter_query/exact'
|
24
|
+
autoload :Like, 'kiroshi/filter_query/like'
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Factory method to create the appropriate query strategy
|
28
|
+
#
|
29
|
+
# This method returns the correct query strategy class based on the
|
30
|
+
# match type provided. It serves as the main entry point for creating
|
31
|
+
# query strategies.
|
32
|
+
#
|
33
|
+
# @param match [Symbol] the type of matching to perform
|
34
|
+
# - :exact for exact matching
|
35
|
+
# - :like for partial matching using SQL LIKE
|
36
|
+
#
|
37
|
+
# @return [Class] the appropriate FilterQuery subclass
|
38
|
+
#
|
39
|
+
# @example Creating an exact match query
|
40
|
+
# query_class = Kiroshi::FilterQuery.for(:exact)
|
41
|
+
# # Returns Kiroshi::FilterQuery::Exact
|
42
|
+
#
|
43
|
+
# @example Creating a LIKE match query
|
44
|
+
# query_class = Kiroshi::FilterQuery.for(:like)
|
45
|
+
# # Returns Kiroshi::FilterQuery::Like
|
46
|
+
#
|
47
|
+
# @raise [ArgumentError] when an unsupported match type is provided
|
48
|
+
#
|
49
|
+
# @since 0.1.1
|
50
|
+
def for(match)
|
51
|
+
case match
|
52
|
+
when :exact
|
53
|
+
Exact
|
54
|
+
when :like
|
55
|
+
Like
|
56
|
+
else
|
57
|
+
raise ArgumentError, "Unsupported match type: #{match}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates a new FilterQuery instance
|
63
|
+
#
|
64
|
+
# @param filter_runner [Kiroshi::FilterRunner] the filter runner instance
|
65
|
+
#
|
66
|
+
# @since 0.1.1
|
67
|
+
def initialize(filter_runner)
|
68
|
+
@filter_runner = filter_runner
|
69
|
+
end
|
70
|
+
|
71
|
+
# Base implementation for applying a filter query
|
72
|
+
#
|
73
|
+
# This method should be overridden by subclasses to provide specific
|
74
|
+
# query logic for each match type.
|
75
|
+
#
|
76
|
+
# @return [ActiveRecord::Relation] the filtered scope
|
77
|
+
#
|
78
|
+
# @raise [NotImplementedError] when called on the base class
|
79
|
+
#
|
80
|
+
# @since 0.1.1
|
81
|
+
def apply
|
82
|
+
raise NotImplementedError, 'Subclasses must implement #apply method'
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
attr_reader :filter_runner
|
88
|
+
|
89
|
+
# @!method filter_runner
|
90
|
+
# @api private
|
91
|
+
# @private
|
92
|
+
#
|
93
|
+
# Returns the filter runner instance
|
94
|
+
#
|
95
|
+
# @return [Kiroshi::FilterRunner] the filter runner instance
|
96
|
+
|
97
|
+
delegate :scope, :attribute, :table_name, :value, to: :filter_runner
|
98
|
+
|
99
|
+
# @!method scope
|
100
|
+
# @api private
|
101
|
+
#
|
102
|
+
# Returns the current scope being filtered
|
103
|
+
#
|
104
|
+
# @return [ActiveRecord::Relation] the scope
|
105
|
+
|
106
|
+
# @!method attribute
|
107
|
+
# @api private
|
108
|
+
#
|
109
|
+
# Returns the attribute name to filter by
|
110
|
+
#
|
111
|
+
# @return [Symbol] the attribute name
|
112
|
+
|
113
|
+
# @!method table_name
|
114
|
+
# @api private
|
115
|
+
#
|
116
|
+
# Returns the table name for the filter
|
117
|
+
#
|
118
|
+
# @return [String] the table name
|
119
|
+
|
120
|
+
# @!method value
|
121
|
+
# @api private
|
122
|
+
#
|
123
|
+
# Returns the filter value
|
124
|
+
#
|
125
|
+
# @return [Object] the filter value
|
126
|
+
end
|
127
|
+
end
|