kiroshi 0.1.1 → 0.3.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.
@@ -6,11 +6,10 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
6
6
  describe '#apply' do
7
7
  subject(:query) { described_class.new(filter_runner) }
8
8
 
9
- let(:filter_runner) { Kiroshi::FilterRunner.new(filter: filter, scope: scope, filters: filters) }
9
+ let(:filter_runner) { Kiroshi::FilterRunner.new(filter: filter, scope: scope, value: filter_value) }
10
10
  let(:filter) { Kiroshi::Filter.new(:name, match: :exact) }
11
11
  let(:scope) { Document.all }
12
12
  let(:filter_value) { 'test_document' }
13
- let(:filters) { { name: filter_value } }
14
13
 
15
14
  let!(:matching_document) { create(:document, name: 'test_document') }
16
15
  let!(:non_matching_document) { create(:document, name: 'other_document') }
@@ -36,7 +35,6 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
36
35
  context 'when filtering by status attribute' do
37
36
  let(:filter) { Kiroshi::Filter.new(:status, match: :exact) }
38
37
  let(:filter_value) { 'published' }
39
- let(:filters) { { status: filter_value } }
40
38
 
41
39
  let!(:published_document) { create(:document, status: 'published') }
42
40
  let!(:draft_document) { create(:document, status: 'draft') }
@@ -63,7 +61,6 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
63
61
  context 'when filtering with numeric values' do
64
62
  let(:filter) { Kiroshi::Filter.new(:priority, match: :exact) }
65
63
  let(:filter_value) { 1 }
66
- let(:filters) { { priority: filter_value } }
67
64
 
68
65
  let!(:high_priority_document) { create(:document, priority: 1) }
69
66
  let!(:medium_priority_document) { create(:document, priority: 2) }
@@ -90,7 +87,6 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
90
87
  context 'when filtering with boolean values' do
91
88
  let(:filter) { Kiroshi::Filter.new(:active, match: :exact) }
92
89
  let(:filter_value) { true }
93
- let(:filters) { { active: filter_value } }
94
90
 
95
91
  let!(:active_document) { create(:document, active: true) }
96
92
  let!(:inactive_document) { create(:document, active: false) }
@@ -154,7 +150,6 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
154
150
  context 'when filter has table configured' do
155
151
  let(:scope) { Document.joins(:tags) }
156
152
  let(:filter_value) { 'ruby' }
157
- let(:filters) { { name: filter_value } }
158
153
 
159
154
  let!(:first_tag) { Tag.find_or_create_by(name: 'ruby') }
160
155
  let!(:second_tag) { Tag.find_or_create_by(name: 'javascript') }
@@ -252,7 +247,6 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
252
247
  context 'when filtering by different attributes with table qualification' do
253
248
  let(:filter) { Kiroshi::Filter.new(:id, match: :exact, table: :tags) }
254
249
  let(:filter_value) { first_tag.id }
255
- let(:filters) { { id: filter_value } }
256
250
 
257
251
  let(:expected_sql) do
258
252
  <<~SQL.squish
@@ -276,5 +270,45 @@ RSpec.describe Kiroshi::FilterQuery::Exact, type: :model do
276
270
  end
277
271
  end
278
272
  end
273
+
274
+ context 'when Filter#column is different from filter_key' do
275
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :exact, column: :full_name) }
276
+ let(:filter_value) { 'John Doe' }
277
+
278
+ let!(:matching_document) { create(:document, full_name: 'John Doe') }
279
+ let!(:non_matching_document) { create(:document, full_name: 'Jane Smith') }
280
+
281
+ let(:expected_sql) do
282
+ <<~SQL.squish
283
+ SELECT "documents".* FROM "documents" WHERE "documents"."full_name" = 'John Doe'
284
+ SQL
285
+ end
286
+
287
+ it 'uses the column name instead of filter_key in SQL' do
288
+ expect(query.apply.to_sql).to eq(expected_sql)
289
+ end
290
+
291
+ it 'returns records that match the column value' do
292
+ expect(query.apply).to include(matching_document)
293
+ end
294
+
295
+ it 'does not return records that do not match the column value' do
296
+ expect(query.apply).not_to include(non_matching_document)
297
+ end
298
+
299
+ context 'with table qualification' do
300
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :exact, table: :documents, column: :full_name) }
301
+
302
+ let(:expected_sql) do
303
+ <<~SQL.squish
304
+ SELECT "documents".* FROM "documents" WHERE "documents"."full_name" = 'John Doe'
305
+ SQL
306
+ end
307
+
308
+ it 'generates SQL with proper table and column qualification' do
309
+ expect(query.apply.to_sql).to eq(expected_sql)
310
+ end
311
+ end
312
+ end
279
313
  end
280
314
  end
@@ -6,11 +6,10 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
6
6
  describe '#apply' do
7
7
  subject(:query) { described_class.new(filter_runner) }
8
8
 
9
- let(:filter_runner) { Kiroshi::FilterRunner.new(filter: filter, scope: scope, filters: filters) }
9
+ let(:filter_runner) { Kiroshi::FilterRunner.new(filter: filter, scope: scope, value: filter_value) }
10
10
  let(:filter) { Kiroshi::Filter.new(:name, match: :like) }
11
11
  let(:scope) { Document.all }
12
12
  let(:filter_value) { 'test' }
13
- let(:filters) { { name: filter_value } }
14
13
 
15
14
  let!(:matching_document) { create(:document, name: 'test_document') }
16
15
  let!(:another_match) { create(:document, name: 'my_test_file') }
@@ -18,7 +17,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
18
17
 
19
18
  let(:expected_sql) do
20
19
  <<~SQL.squish
21
- SELECT "documents".* FROM "documents" WHERE (documents.name LIKE '%test%')
20
+ SELECT "documents".* FROM "documents" WHERE ("documents"."name" LIKE '%test%')
22
21
  SQL
23
22
  end
24
23
 
@@ -41,7 +40,6 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
41
40
  context 'when filtering by status attribute' do
42
41
  let(:filter) { Kiroshi::Filter.new(:status, match: :like) }
43
42
  let(:filter_value) { 'pub' }
44
- let(:filters) { { status: filter_value } }
45
43
 
46
44
  let!(:published_document) { create(:document, status: 'published') }
47
45
  let!(:republished_document) { create(:document, status: 'republished') }
@@ -49,7 +47,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
49
47
 
50
48
  let(:expected_sql) do
51
49
  <<~SQL.squish
52
- SELECT "documents".* FROM "documents" WHERE (documents.status LIKE '%pub%')
50
+ SELECT "documents".* FROM "documents" WHERE ("documents"."status" LIKE '%pub%')
53
51
  SQL
54
52
  end
55
53
 
@@ -73,7 +71,6 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
73
71
  context 'when filtering with numeric values as strings' do
74
72
  let(:filter) { Kiroshi::Filter.new(:version, match: :like) }
75
73
  let(:filter_value) { '1.2' }
76
- let(:filters) { { version: filter_value } }
77
74
 
78
75
  let!(:version_match) { create(:document, version: '1.2.3') }
79
76
  let!(:another_version) { create(:document, version: '2.1.2') }
@@ -81,7 +78,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
81
78
 
82
79
  let(:expected_sql) do
83
80
  <<~SQL.squish
84
- SELECT "documents".* FROM "documents" WHERE (documents.version LIKE '%1.2%')
81
+ SELECT "documents".* FROM "documents" WHERE ("documents"."version" LIKE '%1.2%')
85
82
  SQL
86
83
  end
87
84
 
@@ -107,7 +104,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
107
104
 
108
105
  let(:expected_sql) do
109
106
  <<~SQL.squish
110
- SELECT "documents".* FROM "documents" WHERE (documents.name LIKE '%nonexistent%')
107
+ SELECT "documents".* FROM "documents" WHERE ("documents"."name" LIKE '%nonexistent%')
111
108
  SQL
112
109
  end
113
110
 
@@ -190,7 +187,6 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
190
187
  context 'when filter has table configured' do
191
188
  let(:scope) { Document.joins(:tags) }
192
189
  let(:filter_value) { 'ruby' }
193
- let(:filters) { { name: filter_value } }
194
190
 
195
191
  let!(:first_tag) { Tag.find_or_create_by(name: 'ruby') }
196
192
  let!(:second_tag) { Tag.find_or_create_by(name: 'ruby_on_rails') }
@@ -222,7 +218,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
222
218
 
223
219
  it 'generates SQL with tags table qualification' do
224
220
  result_sql = query.apply.to_sql
225
- expect(result_sql).to include('tags.name LIKE')
221
+ expect(result_sql).to include('"tags"."name" LIKE')
226
222
  end
227
223
 
228
224
  it 'generates SQL with correct LIKE pattern for tag name' do
@@ -249,7 +245,7 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
249
245
 
250
246
  it 'generates SQL with documents table qualification' do
251
247
  result_sql = query.apply.to_sql
252
- expect(result_sql).to include('documents.name LIKE')
248
+ expect(result_sql).to include('"documents"."name" LIKE')
253
249
  end
254
250
 
255
251
  it 'generates SQL with correct LIKE pattern for document name' do
@@ -267,7 +263,52 @@ RSpec.describe Kiroshi::FilterQuery::Like, type: :model do
267
263
 
268
264
  it 'generates SQL with string table qualification' do
269
265
  result_sql = query.apply.to_sql
270
- expect(result_sql).to include('tags.name LIKE')
266
+ expect(result_sql).to include('"tags"."name" LIKE')
267
+ end
268
+ end
269
+ end
270
+
271
+ context 'when Filter#column is different from filter_key' do
272
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :like, column: :full_name) }
273
+ let(:filter_value) { 'John' }
274
+
275
+ let!(:matching_document) { create(:document, full_name: 'John Doe') }
276
+ let!(:another_match) { create(:document, full_name: 'Johnny Smith') }
277
+ let!(:non_matching_document) { create(:document, full_name: 'Jane Wilson') }
278
+
279
+ let(:expected_sql) do
280
+ <<~SQL.squish
281
+ SELECT "documents".* FROM "documents" WHERE ("documents"."full_name" LIKE '%John%')
282
+ SQL
283
+ end
284
+
285
+ it 'uses the column name instead of filter_key in SQL' do
286
+ expect(query.apply.to_sql).to eq(expected_sql)
287
+ end
288
+
289
+ it 'returns records that partially match the column value' do
290
+ expect(query.apply).to include(matching_document)
291
+ end
292
+
293
+ it 'returns multiple records that contain the column value' do
294
+ expect(query.apply).to include(another_match)
295
+ end
296
+
297
+ it 'does not return records that do not contain the column value' do
298
+ expect(query.apply).not_to include(non_matching_document)
299
+ end
300
+
301
+ context 'with table qualification' do
302
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :like, table: :documents, column: :full_name) }
303
+
304
+ let(:expected_sql) do
305
+ <<~SQL.squish
306
+ SELECT "documents".* FROM "documents" WHERE ("documents"."full_name" LIKE '%John%')
307
+ SQL
308
+ end
309
+
310
+ it 'generates SQL with proper table and column qualification' do
311
+ expect(query.apply.to_sql).to eq(expected_sql)
271
312
  end
272
313
  end
273
314
  end
@@ -4,12 +4,12 @@ require 'spec_helper'
4
4
 
5
5
  RSpec.describe Kiroshi::FilterRunner, type: :model do
6
6
  describe '#apply' do
7
- subject(:runner) { described_class.new(filter: filter, scope: scope, filters: filters) }
7
+ subject(:runner) { described_class.new(filter: filter, scope: scope, value: filter_value) }
8
8
 
9
9
  let(:scope) { Document.all }
10
10
  let(:filter_value) { 'test_value' }
11
- let(:filters) { { name: filter_value } }
12
- let!(:matching_document) { create(:document, name: filter_value) }
11
+ let(:document_name) { filter_value }
12
+ let!(:matching_document) { create(:document, name: document_name) }
13
13
  let!(:non_matching_document) { create(:document, name: 'other_value') }
14
14
 
15
15
  context 'when filter match is :exact' do
@@ -39,7 +39,7 @@ RSpec.describe Kiroshi::FilterRunner, type: :model do
39
39
  end
40
40
 
41
41
  it 'generates correct SQL with table name prefix' do
42
- expected_sql = "SELECT \"documents\".* FROM \"documents\" WHERE (documents.name LIKE '%test%')"
42
+ expected_sql = "SELECT \"documents\".* FROM \"documents\" WHERE (\"documents\".\"name\" LIKE '%test%')"
43
43
  expect(runner.apply.to_sql).to eq(expected_sql)
44
44
  end
45
45
  end
@@ -57,8 +57,9 @@ RSpec.describe Kiroshi::FilterRunner, type: :model do
57
57
  end
58
58
 
59
59
  context 'when filter value is not present' do
60
- let(:filter) { Kiroshi::Filter.new(:name) }
61
- let(:filters) { { name: nil } }
60
+ let(:document_name) { 'Some name' }
61
+ let(:filter) { Kiroshi::Filter.new(:name) }
62
+ let(:filter_value) { nil }
62
63
 
63
64
  it 'returns the original scope unchanged' do
64
65
  expect(runner.apply).to eq(scope)
@@ -66,45 +67,69 @@ RSpec.describe Kiroshi::FilterRunner, type: :model do
66
67
  end
67
68
 
68
69
  context 'when filter value is empty string' do
69
- let(:filter) { Kiroshi::Filter.new(:name) }
70
- let(:filters) { { name: '' } }
70
+ let(:document_name) { 'Some name' }
71
+ let(:filter) { Kiroshi::Filter.new(:name) }
72
+ let(:filter_value) { '' }
71
73
 
72
74
  it 'returns the original scope unchanged' do
73
75
  expect(runner.apply).to eq(scope)
74
76
  end
75
77
  end
76
78
 
77
- context 'when filter attribute is not in filters hash' do
78
- let(:filter) { Kiroshi::Filter.new(:status) }
79
- let(:filters) { { name: 'test_value' } }
79
+ context 'with status filter' do
80
+ let(:filter) { Kiroshi::Filter.new(:status, match: :exact) }
81
+ let(:filter_value) { 'finished' }
82
+ let!(:matching_document) { create(:document, name: 'test_name', status: 'finished') }
83
+ let!(:non_matching_document) { create(:document, name: 'other_name', status: 'processing') }
80
84
 
81
- it 'returns the original scope unchanged' do
82
- expect(runner.apply).to eq(scope)
85
+ it 'filters by the configured attribute only returning the matched' do
86
+ expect(runner.apply).to include(matching_document)
83
87
  end
84
- end
85
-
86
- context 'when filters hash is empty' do
87
- let(:filter) { Kiroshi::Filter.new(:name) }
88
- let(:filters) { {} }
89
88
 
90
- it 'returns the original scope unchanged' do
91
- expect(runner.apply).to eq(scope)
89
+ it 'does not return non-matching records' do
90
+ expect(runner.apply).not_to include(non_matching_document)
92
91
  end
93
92
  end
94
93
 
95
- context 'with multiple attributes' do
96
- let(:filter) { Kiroshi::Filter.new(:status, match: :exact) }
97
- let(:filters) { { name: 'test_name', status: 'finished' } }
98
- let!(:matching_document) { create(:document, name: 'test_name', status: 'finished') }
99
- let!(:non_matching_document) { create(:document, name: 'other_name', status: 'processing') }
94
+ context 'when Filter#column is different from filter_key' do
95
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :exact, column: :full_name) }
96
+ let(:filter_value) { 'John Doe' }
100
97
 
101
- it 'filters by the configured attribute only returning the matched' do
98
+ let!(:matching_document) { create(:document, full_name: 'John Doe') }
99
+ let!(:non_matching_document) { create(:document, full_name: 'Jane Smith') }
100
+
101
+ it 'filters using the column name instead of filter_key' do
102
102
  expect(runner.apply).to include(matching_document)
103
103
  end
104
104
 
105
105
  it 'does not return non-matching records' do
106
106
  expect(runner.apply).not_to include(non_matching_document)
107
107
  end
108
+
109
+ it 'generates correct SQL using the column name' do
110
+ expected_sql = "SELECT \"documents\".* FROM \"documents\" WHERE \"documents\".\"full_name\" = 'John Doe'"
111
+ expect(runner.apply.to_sql).to eq(expected_sql)
112
+ end
113
+
114
+ context 'with LIKE match' do
115
+ let(:filter) { Kiroshi::Filter.new(:user_name, match: :like, column: :full_name) }
116
+ let(:filter_value) { 'John' }
117
+
118
+ let!(:partial_match) { create(:document, full_name: 'Johnny Smith') }
119
+
120
+ it 'performs LIKE filtering using the column name' do
121
+ expect(runner.apply).to include(matching_document)
122
+ end
123
+
124
+ it 'includes partial matches using the column name' do
125
+ expect(runner.apply).to include(partial_match)
126
+ end
127
+
128
+ it 'generates correct LIKE SQL using the column name' do
129
+ expected_sql = "SELECT \"documents\".* FROM \"documents\" WHERE (\"documents\".\"full_name\" LIKE '%John%')"
130
+ expect(runner.apply.to_sql).to eq(expected_sql)
131
+ end
132
+ end
108
133
  end
109
134
  end
110
135
  end
@@ -6,19 +6,18 @@ RSpec.describe Kiroshi::Filter, type: :model do
6
6
  describe '#apply' do
7
7
  let(:scope) { Document.all }
8
8
  let(:filter_value) { 'test_value' }
9
- let(:filters) { { name: filter_value } }
10
9
  let!(:matching_document) { create(:document, name: filter_value) }
11
10
  let!(:non_matching_document) { create(:document, name: 'other_value') }
12
11
 
13
12
  context 'when match is :exact' do
14
13
  subject(:filter) { described_class.new(:name, match: :exact) }
15
14
 
16
- it 'returns exact matches' do
17
- expect(filter.apply(scope, filters)).to include(matching_document)
15
+ it 'returns documents matching the filter' do
16
+ expect(filter.apply(scope: scope, value: filter_value)).to include(matching_document)
18
17
  end
19
18
 
20
- it 'does not return non-matching records' do
21
- expect(filter.apply(scope, filters)).not_to include(non_matching_document)
19
+ it 'does not return documents not matching the filter' do
20
+ expect(filter.apply(scope: scope, value: filter_value)).not_to include(non_matching_document)
22
21
  end
23
22
  end
24
23
 
@@ -30,11 +29,11 @@ RSpec.describe Kiroshi::Filter, type: :model do
30
29
  let!(:non_matching_document) { create(:document, name: 'other_value') }
31
30
 
32
31
  it 'returns partial matches' do
33
- expect(filter.apply(scope, filters)).to include(matching_document)
32
+ expect(filter.apply(scope: scope, value: filter_value)).to include(matching_document)
34
33
  end
35
34
 
36
35
  it 'does not return non-matching records' do
37
- expect(filter.apply(scope, filters)).not_to include(non_matching_document)
36
+ expect(filter.apply(scope: scope, value: filter_value)).not_to include(non_matching_document)
38
37
  end
39
38
  end
40
39
 
@@ -42,21 +41,19 @@ RSpec.describe Kiroshi::Filter, type: :model do
42
41
  subject(:filter) { described_class.new(:name) }
43
42
 
44
43
  it 'defaults to exact match returning only exact matches' do
45
- expect(filter.apply(scope, filters)).to include(matching_document)
44
+ expect(filter.apply(scope: scope, value: filter_value)).to include(matching_document)
46
45
  end
47
46
 
48
47
  it 'defaults to exact match returning not returning when filtering by a non-matching value' do
49
- expect(filter.apply(scope, filters)).not_to include(non_matching_document)
48
+ expect(filter.apply(scope: scope, value: filter_value)).not_to include(non_matching_document)
50
49
  end
51
50
  end
52
51
 
53
52
  context 'when filter value is not present' do
54
53
  subject(:filter) { described_class.new(:name) }
55
54
 
56
- let(:filters) { { name: nil } }
57
-
58
55
  it 'returns the original scope unchanged' do
59
- expect(filter.apply(scope, filters)).to eq(scope)
56
+ expect(filter.apply(scope: scope, value: nil)).to eq(scope)
60
57
  end
61
58
  end
62
59
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Kiroshi::Filters::ClassMethods, type: :model do
6
+ subject(:filters_class) { Class.new(Kiroshi::Filters) }
7
+
8
+ let(:filter_instance) { filters_class.new(filters) }
9
+ let(:scope) { Document.all }
10
+ let(:filters) { {} }
11
+
12
+ describe '.filter_by' do
13
+ let(:scope) { Document.all }
14
+ let(:filters) { { name: name } }
15
+ let(:name) { 'test_name' }
16
+
17
+ context 'when adding a new filter' do
18
+ it do
19
+ expect { filters_class.filter_by :name }
20
+ .to change { filter_instance.apply(scope) }
21
+ .from(scope).to(scope.where(name: name))
22
+ end
23
+ end
24
+
25
+ context 'when adding a filter with table qualification' do
26
+ let(:scope) { Document.joins(:tags) }
27
+
28
+ it do
29
+ expect { filters_class.filter_by :name, table: :documents }
30
+ .to change { filter_instance.apply(scope) }
31
+ .from(scope).to(scope.where(documents: { name: name }))
32
+ end
33
+ end
34
+
35
+ context 'when adding a filter with different table' do
36
+ let(:scope) { Document.joins(:tags) }
37
+ let(:filters) { { name: 'ruby' } }
38
+ let(:name) { 'ruby' }
39
+
40
+ it do
41
+ expect { filters_class.filter_by :name, table: :tags }
42
+ .to change { filter_instance.apply(scope) }
43
+ .from(scope).to(scope.where(tags: { name: name }))
44
+ end
45
+ end
46
+
47
+ context 'when adding a like filter with table qualification' do
48
+ let(:scope) { Document.joins(:tags) }
49
+ let(:filters) { { name: 'test' } }
50
+ let(:name) { 'test' }
51
+
52
+ it do
53
+ expect { filters_class.filter_by :name, match: :like, table: :documents }
54
+ .to change { filter_instance.apply(scope) }
55
+ .from(scope).to(scope.where('"documents"."name" LIKE ?', '%test%'))
56
+ end
57
+ end
58
+
59
+ context 'when column is different from filter_key' do
60
+ let(:filters) { { user_name: 'John Doe' } }
61
+
62
+ context 'with exact match' do
63
+ it do
64
+ expect { filters_class.filter_by :user_name, column: :full_name }
65
+ .to change { filter_instance.apply(scope) }
66
+ .from(scope).to(scope.where(full_name: 'John Doe'))
67
+ end
68
+ end
69
+
70
+ context 'with like match' do
71
+ let(:filters) { { user_name: 'John' } }
72
+
73
+ it do
74
+ expect { filters_class.filter_by :user_name, match: :like, column: :full_name }
75
+ .to change { filter_instance.apply(scope) }
76
+ .from(scope).to(scope.where('"documents"."full_name" LIKE ?', '%John%'))
77
+ end
78
+ end
79
+
80
+ context 'with table qualification and different column' do
81
+ let(:scope) { Document.joins(:tags) }
82
+ let(:filters) { { tag_identifier: 'ruby' } }
83
+
84
+ it do
85
+ expect { filters_class.filter_by :tag_identifier, table: :tags, column: :name }
86
+ .to change { filter_instance.apply(scope) }
87
+ .from(scope).to(scope.where(tags: { name: 'ruby' }))
88
+ end
89
+ end
90
+
91
+ context 'with like match, table qualification and different column' do
92
+ let(:scope) { Document.joins(:tags) }
93
+ let(:filters) { { tag_identifier: 'rub' } }
94
+
95
+ it do
96
+ expect { filters_class.filter_by :tag_identifier, match: :like, table: :tags, column: :name }
97
+ .to change { filter_instance.apply(scope) }
98
+ .from(scope).to(scope.where('"tags"."name" LIKE ?', '%rub%'))
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end