pursuit 0.4.3 → 1.0.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.
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