kiroshi 0.1.0 → 0.1.1

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: 3bbe023d89c78eca0371b05303b85c44da60ce794a1c39844b2ab719350cc665
4
- data.tar.gz: aa64d92280278a488c7bb2c5385fc7fd5f28a04a5b7a22aa1cbd1681311bf316
3
+ metadata.gz: 3df16fe842c4fcd160633af8a5e4d91fa19cbb857dc135a31160c1f389a5f6c1
4
+ data.tar.gz: b3f98740895ae5c611d616c36472d77ce412a1086d9d6a9ffe4532a8b3fa2235
5
5
  SHA512:
6
- metadata.gz: 588fb1ce51bb238a8536b08d123a6cd23b8393896eea4f66df436b8fb641e016f517e411a6936ea6277b76c9d34564d44e82b547517b27ec61762634dbaa1ca3
7
- data.tar.gz: 7f90feb28c09bc3858110427fe2266ec16fcc699238689ceea3432ed56a6e839ad1d33d49818e7563998817b3d41fc839f175d5e64bbdb0d838f4375e0d5698a
6
+ metadata.gz: 328641f23218cf3a3a3841af7027f42981dced635c03e47642e5f7bd3a9194d94e13e59a87f51f71adc51344642a682148606daff113ebf80f638e0cb0f5be19
7
+ data.tar.gz: e3cb7920836e0ad2d86d05875c74a57759c5b28d9309124539c61c902adaaaa3a9bf1d0f094e9b19500d23f4034563ac9de234b9fd6f36a21084054bfed09c13
data/README.md CHANGED
@@ -7,16 +7,16 @@
7
7
 
8
8
  ## Yard Documentation
9
9
 
10
- [https://www.rubydoc.info/gems/kiroshi/0.1.0](https://www.rubydoc.info/gems/kiroshi/0.1.0)
10
+ [https://www.rubydoc.info/gems/kiroshi/0.1.1](https://www.rubydoc.info/gems/kiroshi/0.1.1)
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.1.0](https://github.com/darthjee/kiroshi/tree/0.1.0)
17
+ Current Release: [0.1.1](https://github.com/darthjee/kiroshi/tree/0.1.1)
18
18
 
19
- [Next release](https://github.com/darthjee/kiroshi/compare/0.1.0...master)
19
+ [Next release](https://github.com/darthjee/kiroshi/compare/0.1.1...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.permit(:name, :status, :category, :author)
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,10 +143,65 @@ def articles
141
143
  end
142
144
 
143
145
  def article_filters
144
- ArticleFilters.new(params.permit(:title, :published, :tag))
146
+ ArticleFilters.new(params[:filter]&.permit(:title, :published, :tag))
145
147
  end
146
148
  ```
147
149
 
150
+ ##### Joined Tables and Table Qualification
151
+
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:
153
+
154
+ ```ruby
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
161
+
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
+
169
+ ###### Table Qualification Examples
170
+
171
+ ```ruby
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'
201
+ ```
202
+
203
+ The `table` parameter accepts both symbols and strings, and helps resolve column name ambiguity in complex joined queries.
204
+
148
205
  ### Kiroshi::Filter
149
206
 
150
207
  [Filter](https://www.rubydoc.info/gems/kiroshi/Kiroshi/Filter)
@@ -168,6 +225,7 @@ scope = status_filter.apply(scope, { status: 'published' })
168
225
 
169
226
  - `match: :exact` - Performs exact matching (default)
170
227
  - `match: :like` - Performs partial matching using SQL LIKE
228
+ - `table: :table_name` - Specifies which table to filter on (useful for joined queries)
171
229
 
172
230
  ```ruby
173
231
  # Exact match filter
@@ -179,6 +237,16 @@ exact_filter.apply(Document.all, { status: 'published' })
179
237
  like_filter = Kiroshi::Filter.new(:title, match: :like)
180
238
  like_filter.apply(Document.all, { title: 'Ruby' })
181
239
  # Generates: WHERE title LIKE '%Ruby%'
240
+
241
+ # Table-qualified filter for joined queries
242
+ tag_filter = Kiroshi::Filter.new(:name, match: :like, table: :tags)
243
+ tag_filter.apply(Document.joins(:tags), { name: 'programming' })
244
+ # Generates: WHERE tags.name LIKE '%programming%'
245
+
246
+ # Document-specific filter in joined query
247
+ doc_filter = Kiroshi::Filter.new(:title, match: :exact, table: :documents)
248
+ doc_filter.apply(Document.joins(:tags), { title: 'Ruby Guide' })
249
+ # Generates: WHERE documents.title = 'Ruby Guide'
182
250
  ```
183
251
 
184
252
  #### Empty Value Handling
@@ -192,3 +260,24 @@ filter.apply(Document.all, { name: '' }) # Returns original scope
192
260
  filter.apply(Document.all, {}) # Returns original scope
193
261
  filter.apply(Document.all, { name: 'value' }) # Applies filter
194
262
  ```
263
+
264
+ #### Handling Column Name Ambiguity
265
+
266
+ When working with joined tables that have columns with the same name, use the `table` parameter to specify which table's column to filter:
267
+
268
+ ```ruby
269
+ # Without table specification - may cause ambiguity
270
+ scope = Document.joins(:tags) # Both documents and tags have 'name' column
271
+
272
+ # Specify which table to filter on
273
+ name_filter = Kiroshi::Filter.new(:name, match: :like, table: :tags)
274
+ result = name_filter.apply(scope, { name: 'ruby' })
275
+ # Generates: WHERE tags.name LIKE '%ruby%'
276
+
277
+ # Or filter by document name specifically
278
+ doc_name_filter = Kiroshi::Filter.new(:name, match: :like, table: :documents)
279
+ result = doc_name_filter.apply(scope, { name: 'guide' })
280
+ # Generates: WHERE documents.name LIKE '%guide%'
281
+ ```
282
+
283
+ **Priority**: When using `Kiroshi::Filters`, if a filter specifies a `table`, it takes priority over the scope's default table name.
@@ -18,10 +18,34 @@ module Kiroshi
18
18
  #
19
19
  # @since 0.1.0
20
20
  class Filter
21
+ attr_reader :attribute, :match, :table_name
22
+
23
+ # @!method attribute
24
+ # @api private
25
+ #
26
+ # Returns the attribute name to filter by
27
+ #
28
+ # @return [Symbol] the attribute name to filter by
29
+
30
+ # @!method match
31
+ # @api private
32
+ #
33
+ # Returns the matching type (+:exact+ or +:like+)
34
+ #
35
+ # @return [Symbol] the matching type (+:exact+ or +:like+)
36
+
37
+ # @!method table_name
38
+ # @api private
39
+ #
40
+ # Returns the table name to qualify the attribute
41
+ #
42
+ # @return [String, String, nil] the table name or nil if not specified
43
+
21
44
  # Creates a new Filter instance
22
45
  #
23
46
  # @param attribute [Symbol] the attribute name to filter by
24
47
  # @param match [Symbol] the matching type, defaults to :exact
48
+ # @param table [String, Symbol, nil] the table name to qualify the attribute, defaults to nil
25
49
  # @option match [Symbol] :exact performs exact matching (default)
26
50
  # @option match [Symbol] :like performs partial matching using SQL LIKE
27
51
  #
@@ -31,10 +55,14 @@ module Kiroshi
31
55
  # @example Creating a partial match filter
32
56
  # filter = Kiroshi::Filter.new(:name, match: :like)
33
57
  #
58
+ # @example Creating a filter with table qualification
59
+ # filter = Kiroshi::Filter.new(:name, table: 'documents')
60
+ #
34
61
  # @since 0.1.0
35
- def initialize(attribute, match: :exact)
62
+ def initialize(attribute, match: :exact, table: nil)
36
63
  @attribute = attribute
37
64
  @match = match
65
+ @table_name = table
38
66
  end
39
67
 
40
68
  # Applies the filter to the given scope
@@ -58,6 +86,16 @@ module Kiroshi
58
86
  # filter.apply(Article.all, { title: 'Ruby' })
59
87
  # # Generates: WHERE title LIKE '%Ruby%'
60
88
  #
89
+ # @example Applying a filter with table qualification
90
+ # filter = Kiroshi::Filter.new(:name, table: 'documents')
91
+ # filter.apply(Document.joins(:tags), { name: 'report' })
92
+ # # Generates: WHERE documents.name = 'report'
93
+ #
94
+ # @example Applying a filter with table qualification for tags
95
+ # filter = Kiroshi::Filter.new(:name, table: 'tags')
96
+ # filter.apply(Document.joins(:tags), { name: 'ruby' })
97
+ # # Generates: WHERE tags.name = 'ruby'
98
+ #
61
99
  # @example With empty filter value
62
100
  # filter = Kiroshi::Filter.new(:name)
63
101
  # filter.apply(User.all, { name: nil })
@@ -65,35 +103,8 @@ module Kiroshi
65
103
  #
66
104
  # @since 0.1.0
67
105
  def apply(scope, filters)
68
- filter_value = filters[attribute]
69
- return scope unless filter_value.present?
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
106
+ runner = FilterRunner.new(filter: self, scope: scope, filters: filters)
107
+ runner.apply
77
108
  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
109
  end
99
110
  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 => filter_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
+ "%#{filter_value}%"
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,131 @@
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, :filter_value, to: :filter_runner
98
+
99
+ # @!method scope
100
+ # @api private
101
+ # @private
102
+ #
103
+ # Returns the ActiveRecord scope being filtered
104
+ #
105
+ # @return [ActiveRecord::Relation] the scope being filtered
106
+
107
+ # @!method attribute
108
+ # @api private
109
+ # @private
110
+ #
111
+ # Returns the attribute name to filter by
112
+ #
113
+ # @return [Symbol] the attribute name to filter by
114
+
115
+ # @!method table_name
116
+ # @api private
117
+ # @private
118
+ #
119
+ # Returns the table name from the scope
120
+ #
121
+ # @return [String] the table name
122
+
123
+ # @!method filter_value
124
+ # @api private
125
+ # @private
126
+ #
127
+ # Returns the filter value for the current filter's attribute
128
+ #
129
+ # @return [Object, nil] the filter value or nil if not present
130
+ end
131
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kiroshi
4
+ # @api private
5
+ # @author darthjee
6
+ #
7
+ # A filter runner that applies filtering logic to ActiveRecord scopes
8
+ #
9
+ # This class handles the actual application of filter logic to database queries,
10
+ # supporting both exact matches and partial matches using SQL LIKE operations.
11
+ # It separates the filter configuration from the filter execution logic.
12
+ #
13
+ # @example Creating and running a filter
14
+ # filter = Kiroshi::Filter.new(:name, match: :like)
15
+ # runner = Kiroshi::FilterRunner.new(filter: filter, scope: User.all, filters: { name: 'John' })
16
+ # result = runner.apply
17
+ #
18
+ # @since 0.1.0
19
+ class FilterRunner
20
+ # Creates a new FilterRunner instance
21
+ #
22
+ # @param filter [Kiroshi::Filter] the filter configuration
23
+ # @param scope [ActiveRecord::Relation] the scope to filter
24
+ # @param filters [Hash] a hash containing filter values
25
+ #
26
+ # @since 0.1.0
27
+ def initialize(filter:, scope:, filters:)
28
+ @filter = filter
29
+ @scope = scope
30
+ @filters = filters
31
+ end
32
+
33
+ # Applies the filter logic to the scope
34
+ #
35
+ # This method contains the actual filtering logic, checking the filter's
36
+ # match type and applying the appropriate WHERE clause to the scope.
37
+ #
38
+ # @return [ActiveRecord::Relation] the filtered scope
39
+ #
40
+ # @example Applying exact match filter
41
+ # runner = FilterRunner.new(filter: filter, scope: scope, filters: { name: 'John' })
42
+ # runner.apply
43
+ #
44
+ # @example Applying LIKE filter
45
+ # runner = FilterRunner.new(filter: filter, scope: scope, filters: { title: 'Ruby' })
46
+ # runner.apply
47
+ #
48
+ # @example With no matching value
49
+ # runner = FilterRunner.new(filter: filter, scope: scope, filters: { name: nil })
50
+ # runner.apply
51
+ # # Returns the original scope unchanged
52
+ #
53
+ # @since 0.1.1
54
+ def apply
55
+ return scope unless filter_value.present?
56
+
57
+ query_strategy = FilterQuery.for(filter.match).new(self)
58
+ query_strategy.apply
59
+ end
60
+
61
+ # Returns the filter value for the current filter's attribute
62
+ #
63
+ # @return [Object, nil] the filter value or nil if not present
64
+ #
65
+ # @since 0.1.1
66
+ def filter_value
67
+ filters[filter.attribute]
68
+ end
69
+
70
+ # Returns the current scope being filtered
71
+ #
72
+ # @return [ActiveRecord::Relation] the scope
73
+ #
74
+ # @since 0.1.1
75
+ attr_reader :scope
76
+
77
+ # Returns the table name to use for the filter
78
+ #
79
+ # This method prioritizes the filter's table_name over the scope's table_name.
80
+ # If the filter has a specific table_name configured, it uses that;
81
+ # otherwise, it falls back to the scope's table_name.
82
+ #
83
+ # @return [String] the table name to use for filtering
84
+ #
85
+ # @example With filter table_name specified
86
+ # filter = Kiroshi::Filter.new(:name, table: 'tags')
87
+ # runner = FilterRunner.new(filter: filter, scope: Document.joins(:tags), filters: {})
88
+ # runner.table_name # => 'tags'
89
+ #
90
+ # @example Without filter table_name (fallback to scope)
91
+ # filter = Kiroshi::Filter.new(:name)
92
+ # runner = FilterRunner.new(filter: filter, scope: Document.all, filters: {})
93
+ # runner.table_name # => 'documents'
94
+ #
95
+ # @since 0.1.1
96
+ def table_name
97
+ filter_table_name || scope_table_name
98
+ end
99
+
100
+ # @!method scope
101
+ # @api private
102
+ #
103
+ # Returns the current scope being filtered
104
+ #
105
+ # @return [ActiveRecord::Relation] the scope
106
+
107
+ private
108
+
109
+ attr_reader :filter, :filters
110
+
111
+ # @!method filter
112
+ # @api private
113
+ # @private
114
+ #
115
+ # Returns the filter configuration
116
+ #
117
+ # @return [Kiroshi::Filter] the filter configuration
118
+
119
+ # @!method filters
120
+ # @api private
121
+ # @private
122
+ #
123
+ # Returns the hash of filter values
124
+ #
125
+ # @return [Hash] the hash of filter values
126
+
127
+ delegate :attribute, to: :filter
128
+ delegate :table_name, to: :scope, prefix: true
129
+ delegate :table_name, to: :filter, prefix: true
130
+
131
+ # @!method attribute
132
+ # @api private
133
+ #
134
+ # Returns the attribute name to filter by
135
+ #
136
+ # @return [Symbol] the attribute name to filter by
137
+
138
+ # @!method scope_table_name
139
+ # @api private
140
+ #
141
+ # Returns the table name from the scope
142
+ #
143
+ # @return [String] the table name from the scope
144
+
145
+ # @!method filter_table_name
146
+ # @api private
147
+ #
148
+ # Returns the table name from the filter configuration
149
+ #
150
+ # @return [String, nil] the table name from the filter or nil if not specified
151
+ end
152
+ end
@@ -43,11 +43,13 @@ module Kiroshi
43
43
  # be applied when {#apply} is called. Each call creates a new {Filter}
44
44
  # instance with the specified configuration.
45
45
  #
46
- # @param attribute [Symbol] the attribute name to filter by
47
- # @param options [Hash] additional options passed to {Filter#initialize}
48
- # @option options [Symbol] :match (:exact) the matching type
49
- # - +:exact+ for exact matching (default)
50
- # - +:like+ for partial matching using SQL LIKE
46
+ # @overload filter_by(attribute, **options)
47
+ # @param attribute [Symbol] the attribute name to filter by
48
+ # @param options [Hash] additional options passed to {Filter#initialize}
49
+ # @option options [Symbol] :match (:exact) the matching type
50
+ # - +:exact+ for exact matching (default)
51
+ # - +:like+ for partial matching using SQL LIKE
52
+ # @option options [String, Symbol, nil] :table (nil) the table name to qualify the attribute
51
53
  #
52
54
  # @return [Filter] the new filter instance
53
55
  #
@@ -70,6 +72,11 @@ module Kiroshi
70
72
  # filter_by :payment_method
71
73
  # end
72
74
  #
75
+ # @example Filter with table qualification
76
+ # class DocumentTagFilters < Kiroshi::Filters
77
+ # filter_by :name, table: :tags
78
+ # end
79
+ #
73
80
  # @since 0.1.0
74
81
  def filter_by(attribute, **)
75
82
  Filter.new(attribute, **).tap do |filter|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kiroshi
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end