pursuit 0.4.3 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubygem.yaml +46 -0
  3. data/.ruby-version +1 -1
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +127 -86
  6. data/LICENSE +174 -21
  7. data/README.md +210 -27
  8. data/bin/console +10 -0
  9. data/config.ru +2 -3
  10. data/lib/pursuit/aggregate_modifier_not_found.rb +20 -0
  11. data/lib/pursuit/aggregate_modifier_required.rb +20 -0
  12. data/lib/pursuit/aggregate_modifiers_not_available.rb +13 -0
  13. data/lib/pursuit/attribute_not_found.rb +20 -0
  14. data/lib/pursuit/constants.rb +1 -1
  15. data/lib/pursuit/error.rb +7 -0
  16. data/lib/pursuit/predicate_parser.rb +181 -0
  17. data/lib/pursuit/predicate_search.rb +83 -0
  18. data/lib/pursuit/predicate_transform.rb +231 -0
  19. data/lib/pursuit/query_error.rb +7 -0
  20. data/lib/pursuit/simple_search.rb +64 -0
  21. data/lib/pursuit/term_parser.rb +44 -0
  22. data/lib/pursuit/term_search.rb +69 -0
  23. data/lib/pursuit/term_transform.rb +35 -0
  24. data/lib/pursuit.rb +19 -5
  25. data/pursuit.gemspec +5 -18
  26. data/spec/internal/app/models/application_record.rb +5 -0
  27. data/spec/internal/app/models/product.rb +25 -9
  28. data/spec/internal/app/models/product_category.rb +23 -1
  29. data/spec/internal/app/models/product_variation.rb +26 -1
  30. data/spec/lib/pursuit/predicate_parser_spec.rb +1604 -0
  31. data/spec/lib/pursuit/predicate_search_spec.rb +80 -0
  32. data/spec/lib/pursuit/predicate_transform_spec.rb +624 -0
  33. data/spec/lib/pursuit/simple_search_spec.rb +59 -0
  34. data/spec/lib/pursuit/term_parser_spec.rb +271 -0
  35. data/spec/lib/pursuit/term_search_spec.rb +71 -0
  36. data/spec/lib/pursuit/term_transform_spec.rb +105 -0
  37. data/spec/spec_helper.rb +2 -3
  38. data/travis/gemfiles/{5.2.gemfile → 7.1.gemfile} +2 -2
  39. metadata +38 -197
  40. data/.travis.yml +0 -25
  41. data/lib/pursuit/dsl.rb +0 -28
  42. data/lib/pursuit/railtie.rb +0 -13
  43. data/lib/pursuit/search.rb +0 -172
  44. data/lib/pursuit/search_options.rb +0 -86
  45. data/lib/pursuit/search_term_parser.rb +0 -46
  46. data/spec/lib/pursuit/dsl_spec.rb +0 -22
  47. data/spec/lib/pursuit/search_options_spec.rb +0 -146
  48. data/spec/lib/pursuit/search_spec.rb +0 -516
  49. data/spec/lib/pursuit/search_term_parser_spec.rb +0 -34
  50. data/travis/gemfiles/6.0.gemfile +0 -8
  51. data/travis/gemfiles/6.1.gemfile +0 -8
  52. data/travis/gemfiles/7.0.gemfile +0 -8
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Pursuit::DSL do
4
- subject(:record) { Product.new }
5
-
6
- describe '.search_options' do
7
- subject(:search_options) { record.class.search_options }
8
-
9
- it { is_expected.to be_a(Pursuit::SearchOptions) }
10
- end
11
-
12
- describe '.search' do
13
- subject(:search) { record.class.search('funky') }
14
-
15
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
16
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
17
-
18
- it 'is expected to return the matching records' do
19
- expect(search).to contain_exactly(product_b)
20
- end
21
- end
22
- end
@@ -1,146 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Pursuit::SearchOptions do
4
- subject(:search_options) { described_class.new(Product) }
5
-
6
- let(:title_length_node_builder) do
7
- proc do
8
- Arel::Nodes::NamedFunction.new('LENGTH', [Product.arel_table[:title]])
9
- end
10
- end
11
-
12
- describe '#record_class' do
13
- subject(:record_class) { search_options.record_class }
14
-
15
- it 'is expected to eq the class passed during initialization' do
16
- expect(record_class).to eq(Product)
17
- end
18
- end
19
-
20
- describe '#relations' do
21
- subject(:relations) { search_options.relations }
22
-
23
- before do
24
- search_options.relation :variations, :title, :stock_status
25
- end
26
-
27
- it 'is expected to contain the correct relations' do
28
- expect(relations).to eq(variations: %i[title stock_status])
29
- end
30
- end
31
-
32
- describe '#keyed_attributes' do
33
- subject(:keyed_attributes) { search_options.keyed_attributes }
34
-
35
- before do
36
- search_options.attribute :title, keyed: false
37
- search_options.attribute :title_length, &title_length_node_builder
38
- search_options.attribute :description
39
- search_options.attribute :rating, unkeyed: false
40
- end
41
-
42
- it 'is expected to contain the correct keyed attributes' do
43
- expect(keyed_attributes.keys).to contain_exactly(:title_length, :description, :rating)
44
- end
45
-
46
- it 'is expected to set a default node builder for attributes declared without a block' do
47
- expect(keyed_attributes[:description].call).to eq(Product.arel_table[:description])
48
- end
49
-
50
- it 'is expected to set a custom node builder for attributes declared with a block' do
51
- expect(keyed_attributes[:title_length]).to eq(title_length_node_builder)
52
- end
53
- end
54
-
55
- describe '#unkeyed_attributes' do
56
- subject(:unkeyed_attributes) { search_options.unkeyed_attributes }
57
-
58
- before do
59
- search_options.attribute :title, keyed: false
60
- search_options.attribute :title_length, &title_length_node_builder
61
- search_options.attribute :description
62
- search_options.attribute :rating, unkeyed: false
63
- end
64
-
65
- it 'is expected to contain the correct unkeyed attributes' do
66
- expect(unkeyed_attributes.keys).to contain_exactly(:title, :title_length, :description)
67
- end
68
-
69
- it 'is expected to set a default node builder for attributes declared without a block' do
70
- expect(unkeyed_attributes[:title].call).to eq(Product.arel_table[:title])
71
- end
72
-
73
- it 'is expected to set a custom node builder for attributes declared with a block' do
74
- expect(unkeyed_attributes[:title_length]).to eq(title_length_node_builder)
75
- end
76
- end
77
-
78
- describe '#relation' do
79
- subject(:relation) { search_options.relation(:variations, :title, :stock_status) }
80
-
81
- it 'is expected to add the relation to #relations' do
82
- expect { relation }.to change(search_options, :relations).from({}).to(variations: %i[title stock_status])
83
- end
84
- end
85
-
86
- describe '#attribute' do
87
- subject(:attribute) { search_options.attribute(:description) }
88
-
89
- it { is_expected.to be_nil }
90
-
91
- it 'is expected to add the attribute to #attributes' do
92
- expect { attribute }.to change(search_options.attributes, :keys).from([]).to(%i[description])
93
- end
94
-
95
- it 'is expected to allow keyed searching by default' do
96
- attribute
97
- expect(search_options.attributes[:description].keyed).to be(true)
98
- end
99
-
100
- it 'is expected to allow unkeyed searching by default' do
101
- attribute
102
- expect(search_options.attributes[:description].unkeyed).to be(true)
103
- end
104
-
105
- it 'is expected to query the #term_name attribute' do
106
- attribute
107
- expect(search_options.attributes[:description].block.call).to eq(Product.arel_table[:description])
108
- end
109
-
110
- context 'when passing the attribute name to search' do
111
- subject(:attribute) { search_options.attribute(:desc, :description) }
112
-
113
- it 'is expected to query the #attribute_name attribute' do
114
- attribute
115
- expect(search_options.attributes[:desc].block.call).to eq(Product.arel_table[:description])
116
- end
117
- end
118
-
119
- context 'when passing :keyed eq false' do
120
- subject(:attribute) { search_options.attribute(:description, keyed: false) }
121
-
122
- it 'is expected to disallow keyed searching' do
123
- attribute
124
- expect(search_options.attributes[:description].keyed).to be(false)
125
- end
126
- end
127
-
128
- context 'when passing :unkeyed eq false' do
129
- subject(:attribute) { search_options.attribute(:description, unkeyed: false) }
130
-
131
- it 'is expected to disallow unkeyed searching' do
132
- attribute
133
- expect(search_options.attributes[:description].unkeyed).to be(false)
134
- end
135
- end
136
-
137
- context 'when passing a block' do
138
- subject(:attribute) { search_options.attribute(:description, &title_length_node_builder) }
139
-
140
- it 'is expected to query the result of the passed block' do
141
- attribute
142
- expect(search_options.attributes[:description].block).to eq(title_length_node_builder)
143
- end
144
- end
145
- end
146
- end
@@ -1,516 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Pursuit::Search do
4
- subject(:search) { described_class.new(search_options) }
5
-
6
- let(:search_options) do
7
- Pursuit::SearchOptions.new(Product) do |o|
8
- o.relation :category, :name
9
- o.relation :variations, :title, :stock_status
10
-
11
- o.attribute :title
12
- o.attribute :description
13
- o.attribute :rating, unkeyed: false
14
- o.attribute :title_length, unkeyed: false do
15
- Arel::Nodes::NamedFunction.new('LENGTH', [Product.arel_table[:title]])
16
- end
17
-
18
- o.attribute :cat, :category_id
19
- end
20
- end
21
-
22
- describe '#perform' do
23
- subject(:perform) { search.perform(query) }
24
-
25
- context 'when passed a blank query' do
26
- let(:query) { '' }
27
-
28
- let(:product_a) { Product.create!(title: 'Alpha') }
29
- let(:product_b) { Product.create!(title: 'Beta') }
30
-
31
- before do
32
- product_a
33
- product_b
34
- end
35
-
36
- it 'is expected to contain all records' do
37
- expect(perform).to contain_exactly(product_a, product_b)
38
- end
39
- end
40
-
41
- context 'when passed an unkeyed query' do
42
- let(:query) { 'shirt' }
43
-
44
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
45
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
46
- let(:product_c) { Product.create!(title: 'Socks') }
47
-
48
- before do
49
- product_a
50
- product_b
51
- product_c
52
- end
53
-
54
- it 'is expected to contain the matching records' do
55
- expect(perform).to contain_exactly(product_a, product_b)
56
- end
57
- end
58
-
59
- context 'when passed an `equal to` keyed attribute query' do
60
- let(:query) { 'title=="Funky Shirt"' }
61
-
62
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
63
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
64
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4') }
65
-
66
- before do
67
- product_a
68
- product_b
69
- product_c
70
- end
71
-
72
- it 'is expected to contain the matching records' do
73
- expect(perform).to contain_exactly(product_b)
74
- end
75
- end
76
-
77
- context 'when passed a `not equal to` keyed attribute query' do
78
- let(:query) { 'title!="Funky Shirt"' }
79
-
80
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
81
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
82
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4') }
83
-
84
- before do
85
- product_a
86
- product_b
87
- product_c
88
- end
89
-
90
- it 'is expected to contain the matching records' do
91
- expect(perform).to contain_exactly(product_a, product_c)
92
- end
93
- end
94
-
95
- context 'when passed a `match` keyed attribute query' do
96
- let(:query) { 'title*=shirt' }
97
-
98
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
99
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
100
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4') }
101
-
102
- before do
103
- product_a
104
- product_b
105
- product_c
106
- end
107
-
108
- it 'is expected to contain the matching records' do
109
- expect(perform).to contain_exactly(product_a, product_b)
110
- end
111
- end
112
-
113
- context 'when passed a `not match` keyed attribute query' do
114
- let(:query) { 'title!*=socks' }
115
-
116
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
117
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
118
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4') }
119
-
120
- before do
121
- product_a
122
- product_b
123
- product_c
124
- end
125
-
126
- it 'is expected to contain the matching records' do
127
- expect(perform).to contain_exactly(product_a, product_b)
128
- end
129
- end
130
-
131
- context 'when passed a numeric `not equal to` keyed attribute query' do
132
- let(:query) { 'rating!=2' }
133
-
134
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
135
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
136
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
137
-
138
- before do
139
- product_a
140
- product_b
141
- product_c
142
- end
143
-
144
- it 'is expected to contain the matching records' do
145
- expect(perform).to contain_exactly(product_b, product_c)
146
- end
147
- end
148
-
149
- context 'when passed a `greater than` keyed attribute query' do
150
- let(:query) { 'rating>2' }
151
-
152
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
153
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
154
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
155
-
156
- before do
157
- product_a
158
- product_b
159
- product_c
160
- end
161
-
162
- it 'is expected to contain the matching records' do
163
- expect(perform).to contain_exactly(product_b, product_c)
164
- end
165
- end
166
-
167
- context 'when passed a `greater than or equal to` keyed attribute query' do
168
- let(:query) { 'rating>=4' }
169
-
170
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
171
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
172
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
173
-
174
- before do
175
- product_a
176
- product_b
177
- product_c
178
- end
179
-
180
- it 'is expected to contain the matching records' do
181
- expect(perform).to contain_exactly(product_b, product_c)
182
- end
183
- end
184
-
185
- context 'when passed a `less than` keyed attribute query' do
186
- let(:query) { 'rating<5' }
187
-
188
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
189
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
190
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
191
-
192
- before do
193
- product_a
194
- product_b
195
- product_c
196
- end
197
-
198
- it 'is expected to contain the matching records' do
199
- expect(perform).to contain_exactly(product_a, product_b)
200
- end
201
- end
202
-
203
- context 'when passed a `less than or equal to` keyed attribute query' do
204
- let(:query) { 'rating<=4' }
205
-
206
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
207
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
208
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
209
-
210
- before do
211
- product_a
212
- product_b
213
- product_c
214
- end
215
-
216
- it 'is expected to contain the matching records' do
217
- expect(perform).to contain_exactly(product_a, product_b)
218
- end
219
- end
220
-
221
- context 'when passed a `greater than` and `less than` keyed attribute query' do
222
- let(:query) { 'rating>2 rating<5' }
223
-
224
- let(:product_a) { Product.create!(title: 'Plain Shirt', rating: 2) }
225
- let(:product_b) { Product.create!(title: 'Funky Shirt', rating: 4) }
226
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', rating: 5) }
227
-
228
- before do
229
- product_a
230
- product_b
231
- product_c
232
- end
233
-
234
- it 'is expected to contain the matching records' do
235
- expect(perform).to contain_exactly(product_b)
236
- end
237
- end
238
-
239
- context 'when passed a virtual keyed attribute query' do
240
- let(:query) { 'title_length==5' }
241
-
242
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
243
- let(:product_b) { Product.create!(title: 'Socks') }
244
-
245
- before do
246
- product_a
247
- product_b
248
- end
249
-
250
- it 'is expected to contain the matching records' do
251
- expect(perform).to contain_exactly(product_b)
252
- end
253
- end
254
-
255
- context 'when querying a custom attribute whose name matches a reflection' do
256
- let(:query) { 'cat==shirts' }
257
-
258
- let(:shirts_category) { ProductCategory.create!(id: 'shirts', name: 'The Shirt Collection') }
259
- let(:socks_category) { ProductCategory.create!(id: 'socks', name: 'The Sock Collection') }
260
-
261
- let(:product_a) { Product.create!(title: 'Plain Shirt', category: shirts_category) }
262
- let(:product_b) { Product.create!(title: 'Funky Shirt', category: shirts_category) }
263
- let(:product_c) { Product.create!(title: 'Socks - Pack of 4', category: socks_category) }
264
-
265
- before do
266
- product_a
267
- product_b
268
- product_c
269
- end
270
-
271
- it 'is expected to contain the matching records' do
272
- expect(perform).to contain_exactly(product_a, product_b)
273
- end
274
- end
275
-
276
- context 'when searching a #has_many relationship' do
277
- context 'when passed a `match` relationship search query' do
278
- let(:query) { 'variations*=green' }
279
-
280
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
281
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
282
-
283
- let(:product_variation_a) { ProductVariation.create!(product: product_a, title: 'Red') }
284
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
285
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
286
-
287
- before do
288
- product_a
289
- product_b
290
-
291
- product_variation_a
292
- product_variation_b
293
- product_variation_c
294
- end
295
-
296
- it 'is expected to contain the matching records' do
297
- expect(perform).to contain_exactly(product_b)
298
- end
299
- end
300
-
301
- context 'when passed an `equal to` relationship count query' do
302
- let(:query) { 'variations==1' }
303
-
304
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
305
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
306
- let(:product_c) { Product.create!(title: 'Socks') }
307
-
308
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
309
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
310
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
311
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
312
-
313
- before do
314
- product_a
315
- product_b
316
- product_c
317
-
318
- product_variation_a
319
- product_variation_b
320
- product_variation_c
321
- product_variation_d
322
- end
323
-
324
- it 'is expected to contain the matching records' do
325
- expect(perform).to contain_exactly(product_c)
326
- end
327
- end
328
-
329
- context 'when passed a `greater than` relationship count query' do
330
- let(:query) { 'variations>1' }
331
-
332
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
333
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
334
- let(:product_c) { Product.create!(title: 'Socks') }
335
-
336
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
337
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
338
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
339
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
340
- let(:product_variation_e) { ProductVariation.create!(product: product_a, title: 'Black') }
341
- let(:product_variation_f) { ProductVariation.create!(product: product_a, title: 'Gray') }
342
-
343
- before do
344
- product_a
345
- product_b
346
- product_c
347
-
348
- product_variation_a
349
- product_variation_b
350
- product_variation_c
351
- product_variation_d
352
- product_variation_e
353
- product_variation_f
354
- end
355
-
356
- it 'is expected to contain the matching records' do
357
- expect(perform).to contain_exactly(product_a, product_b)
358
- end
359
- end
360
-
361
- context 'when passed a `greater than or equal to` relationship count query' do
362
- let(:query) { 'variations>=2' }
363
-
364
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
365
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
366
- let(:product_c) { Product.create!(title: 'Socks') }
367
-
368
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
369
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
370
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
371
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
372
- let(:product_variation_e) { ProductVariation.create!(product: product_a, title: 'Black') }
373
- let(:product_variation_f) { ProductVariation.create!(product: product_a, title: 'Gray') }
374
-
375
- before do
376
- product_a
377
- product_b
378
- product_c
379
-
380
- product_variation_a
381
- product_variation_b
382
- product_variation_c
383
- product_variation_d
384
- product_variation_e
385
- product_variation_f
386
- end
387
-
388
- it 'is expected to contain the matching records' do
389
- expect(perform).to contain_exactly(product_a, product_b)
390
- end
391
- end
392
-
393
- context 'when passed a `less than` relationship count query' do
394
- let(:query) { 'variations<3' }
395
-
396
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
397
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
398
- let(:product_c) { Product.create!(title: 'Socks') }
399
-
400
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
401
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
402
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
403
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
404
- let(:product_variation_e) { ProductVariation.create!(product: product_a, title: 'Black') }
405
- let(:product_variation_f) { ProductVariation.create!(product: product_a, title: 'Gray') }
406
-
407
- before do
408
- product_a
409
- product_b
410
- product_c
411
-
412
- product_variation_a
413
- product_variation_b
414
- product_variation_c
415
- product_variation_d
416
- product_variation_e
417
- product_variation_f
418
- end
419
-
420
- it 'is expected to contain the matching records' do
421
- expect(perform).to contain_exactly(product_a, product_c)
422
- end
423
- end
424
-
425
- context 'when passed a `less than or equal to` relationship count query' do
426
- let(:query) { 'variations<=2' }
427
-
428
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
429
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
430
- let(:product_c) { Product.create!(title: 'Socks') }
431
-
432
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
433
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
434
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
435
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
436
- let(:product_variation_e) { ProductVariation.create!(product: product_a, title: 'Black') }
437
- let(:product_variation_f) { ProductVariation.create!(product: product_a, title: 'Gray') }
438
-
439
- before do
440
- product_a
441
- product_b
442
- product_c
443
-
444
- product_variation_a
445
- product_variation_b
446
- product_variation_c
447
- product_variation_d
448
- product_variation_e
449
- product_variation_f
450
- end
451
-
452
- it 'is expected to contain the matching records' do
453
- expect(perform).to contain_exactly(product_a, product_c)
454
- end
455
- end
456
-
457
- context 'when passed a `greater than` and `less than` relationship count query' do
458
- let(:query) { 'variations>1 variations<3' }
459
-
460
- let(:product_a) { Product.create!(title: 'Plain Shirt') }
461
- let(:product_b) { Product.create!(title: 'Funky Shirt') }
462
- let(:product_c) { Product.create!(title: 'Socks') }
463
-
464
- let(:product_variation_a) { ProductVariation.create!(product: product_b, title: 'Red') }
465
- let(:product_variation_b) { ProductVariation.create!(product: product_b, title: 'Green') }
466
- let(:product_variation_c) { ProductVariation.create!(product: product_b, title: 'Blue') }
467
- let(:product_variation_d) { ProductVariation.create!(product: product_c, title: 'White') }
468
- let(:product_variation_e) { ProductVariation.create!(product: product_a, title: 'Black') }
469
- let(:product_variation_f) { ProductVariation.create!(product: product_a, title: 'Gray') }
470
-
471
- before do
472
- product_a
473
- product_b
474
- product_c
475
-
476
- product_variation_a
477
- product_variation_b
478
- product_variation_c
479
- product_variation_d
480
- product_variation_e
481
- product_variation_f
482
- end
483
-
484
- it 'is expected to contain the matching records' do
485
- expect(perform).to contain_exactly(product_a)
486
- end
487
- end
488
- end
489
-
490
- context 'when searching a #belongs_to relationship' do
491
- context 'when passed a `match` relationship search query' do
492
- let(:query) { 'category*=shirt' }
493
-
494
- let(:product_category_a) { ProductCategory.create!(id: 'one', name: 'Shirts') }
495
- let(:product_category_b) { ProductCategory.create!(id: 'two', name: 'Socks') }
496
-
497
- let(:product_a) { Product.create!(category: product_category_a, title: 'Plain Shirt') }
498
- let(:product_b) { Product.create!(category: product_category_a, title: 'Funky Shirt') }
499
- let(:product_c) { Product.create!(category: product_category_b, title: 'White Socks') }
500
-
501
- before do
502
- product_category_a
503
- product_category_b
504
-
505
- product_a
506
- product_b
507
- product_c
508
- end
509
-
510
- it 'is expected to contain the matching records' do
511
- expect(perform).to contain_exactly(product_a, product_b)
512
- end
513
- end
514
- end
515
- end
516
- end