rasti-db 2.0.0 → 2.3.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -3
  3. data/lib/rasti/db.rb +11 -1
  4. data/lib/rasti/db/collection.rb +10 -1
  5. data/lib/rasti/db/computed_attribute.rb +22 -0
  6. data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
  7. data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
  8. data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
  9. data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
  10. data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
  11. data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
  12. data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
  13. data/lib/rasti/db/nql/nodes/array_content.rb +21 -0
  14. data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
  15. data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
  16. data/lib/rasti/db/nql/nodes/comparisons/base.rb +15 -1
  17. data/lib/rasti/db/nql/nodes/comparisons/equal.rb +0 -4
  18. data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +0 -4
  19. data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +0 -4
  20. data/lib/rasti/db/nql/nodes/comparisons/include.rb +0 -4
  21. data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +0 -4
  22. data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +0 -4
  23. data/lib/rasti/db/nql/nodes/comparisons/like.rb +0 -4
  24. data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +0 -4
  25. data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +0 -4
  26. data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
  27. data/lib/rasti/db/nql/nodes/constants/array.rb +17 -0
  28. data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
  29. data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
  30. data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
  31. data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
  32. data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
  33. data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
  34. data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
  35. data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
  36. data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
  37. data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
  38. data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
  39. data/lib/rasti/db/nql/syntax.rb +262 -44
  40. data/lib/rasti/db/nql/syntax.treetop +27 -14
  41. data/lib/rasti/db/query.rb +42 -14
  42. data/lib/rasti/db/type_converters/postgres.rb +32 -36
  43. data/lib/rasti/db/type_converters/postgres_types/array.rb +11 -9
  44. data/lib/rasti/db/type_converters/postgres_types/hstore.rb +10 -9
  45. data/lib/rasti/db/type_converters/postgres_types/json.rb +17 -14
  46. data/lib/rasti/db/type_converters/postgres_types/jsonb.rb +17 -14
  47. data/lib/rasti/db/type_converters/sqlite.rb +62 -0
  48. data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
  49. data/lib/rasti/db/version.rb +1 -1
  50. data/rasti-db.gemspec +1 -0
  51. data/spec/collection_spec.rb +19 -11
  52. data/spec/computed_attribute_spec.rb +32 -0
  53. data/spec/minitest_helper.rb +32 -5
  54. data/spec/model_spec.rb +1 -1
  55. data/spec/nql/computed_attributes_spec.rb +29 -0
  56. data/spec/nql/filter_condition_spec.rb +23 -4
  57. data/spec/nql/filter_condition_strategies_spec.rb +112 -0
  58. data/spec/nql/syntax_parser_spec.rb +36 -5
  59. data/spec/query_spec.rb +254 -39
  60. data/spec/type_converters/sqlite_spec.rb +66 -0
  61. metadata +38 -3
  62. data/lib/rasti/db/nql/nodes/field.rb +0 -23
@@ -31,7 +31,7 @@ describe 'NQL::SyntaxParser' do
31
31
  proposition = tree.proposition
32
32
  proposition.must_be_instance_of node_class
33
33
  proposition.comparator.text_value.must_equal comparator
34
- proposition.field.text_value.must_equal 'column'
34
+ proposition.attribute.text_value.must_equal 'column'
35
35
  proposition.argument.text_value.must_equal 'value'
36
36
  end
37
37
  end
@@ -44,7 +44,7 @@ describe 'NQL::SyntaxParser' do
44
44
  proposition = tree.proposition
45
45
  proposition.must_be_instance_of Rasti::DB::NQL::Nodes::Comparisons::Equal
46
46
  proposition.comparator.text_value.must_equal '='
47
- proposition.field.text_value.must_equal 'column'
47
+ proposition.attribute.text_value.must_equal 'column'
48
48
  proposition.argument.text_value.must_equal 'value'
49
49
  end
50
50
 
@@ -128,12 +128,19 @@ describe 'NQL::SyntaxParser' do
128
128
 
129
129
  end
130
130
 
131
- it 'must parse expression with field with tables' do
131
+ it 'must parse expression with attribute with tables' do
132
132
  tree = parse 'relation_table_one.relation_table_two.column = 1'
133
133
 
134
- left_hand_operand = tree.proposition.field
134
+ left_hand_operand = tree.proposition.attribute
135
135
  left_hand_operand.tables.must_equal ['relation_table_one', 'relation_table_two']
136
- left_hand_operand.column.must_equal 'column'
136
+ left_hand_operand.column.must_equal :column
137
+ end
138
+
139
+ it 'must parse expression with computed attribute' do
140
+ tree = parse 'comments_count = 1'
141
+ computed = tree.proposition.attribute
142
+ computed.tables.must_equal []
143
+ computed.computed_attributes(Users).must_equal [:comments_count]
137
144
  end
138
145
 
139
146
  end
@@ -206,4 +213,28 @@ describe 'NQL::SyntaxParser' do
206
213
 
207
214
  end
208
215
 
216
+ describe 'Array' do
217
+
218
+ it 'must parse array with one element' do
219
+ tree = parse 'column = [ a ]'
220
+ tree.proposition.argument.value.must_equal ['a']
221
+ end
222
+
223
+ it 'must parse array with many elements' do
224
+ tree = parse 'column = [ a, b, c ]'
225
+ tree.proposition.argument.value.must_equal ['a', 'b', 'c']
226
+ end
227
+
228
+ it 'must parse array respecting content types' do
229
+ tree = parse 'column = [ true, 12:00, 1.1, 1, "literal string", string ]'
230
+ tree.proposition.argument.value.must_equal [true, Timing::TimeInZone.parse('12:00').to_s, 1.1, 1, "literal string", 'string']
231
+ end
232
+
233
+ it 'must parse array with literal string allowing reserved characters in conflict with array' do
234
+ tree = parse 'column = [ ",", "[", "]", "[,", "],", "[,]", "simple literal" ]'
235
+ tree.proposition.argument.value.must_equal [ ',', '[', ']', '[,', '],', '[,]', 'simple literal' ]
236
+ end
237
+
238
+ end
239
+
209
240
  end
data/spec/query_spec.rb CHANGED
@@ -5,13 +5,13 @@ describe 'Query' do
5
5
  before do
6
6
  custom_db[:languages].insert name: 'Spanish'
7
7
 
8
- 1.upto(10) do |i|
8
+ 1.upto(10) do |i|
9
9
  db[:users].insert name: "User #{i}"
10
10
 
11
- db[:people].insert user_id: i,
12
- document_number: "document_#{i}",
13
- first_name: "Name #{i}",
14
- last_name: "Last Name #{i}",
11
+ db[:people].insert user_id: i,
12
+ document_number: "document_#{i}",
13
+ first_name: "Name #{i}",
14
+ last_name: "Last Name #{i}",
15
15
  birth_date: Date.parse('2020-04-24')
16
16
 
17
17
  db[:languages_people].insert language_id: 1, document_number: "document_#{i}"
@@ -22,7 +22,7 @@ describe 'Query' do
22
22
  db[:posts].insert user_id: 4, title: 'Best post', body: '...', language_id: 1
23
23
 
24
24
  1.upto(3) { |i| db[:categories].insert name: "Category #{i}" }
25
-
25
+
26
26
  db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 1'
27
27
  db[:comments].insert post_id: 1, user_id: 7, text: 'Comment 2'
28
28
  db[:comments].insert post_id: 2, user_id: 2, text: 'Comment 3'
@@ -35,11 +35,13 @@ describe 'Query' do
35
35
  end
36
36
 
37
37
  let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users], environment: environment }
38
-
38
+
39
39
  let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts], environment: environment }
40
-
40
+
41
41
  let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments], environment: environment }
42
42
 
43
+ let(:people_query) { Rasti::DB::Query.new collection_class: People, dataset: db[:people], environment: environment }
44
+
43
45
  let(:languages_query) { Rasti::DB::Query.new collection_class: Languages, dataset: custom_db[:languages], environment: environment }
44
46
 
45
47
  it 'Count' do
@@ -87,8 +89,8 @@ describe 'Query' do
87
89
  post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
88
90
 
89
91
  selected_attributes = {
90
- user: [:id],
91
- 'user.person' => [:document_number, :user_id],
92
+ user: [:id],
93
+ 'user.person' => [:document_number, :user_id],
92
94
  'user.person.languages' => [:id],
93
95
  categories: [:id]
94
96
  }
@@ -99,7 +101,7 @@ describe 'Query' do
99
101
  .all
100
102
  .must_equal [post]
101
103
  end
102
-
104
+
103
105
  it 'Exclude graph attributes' do
104
106
  language = Language.new custom_db[:languages].where(id: 1).select(:id).first
105
107
 
@@ -112,8 +114,8 @@ describe 'Query' do
112
114
  post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
113
115
 
114
116
  excluded_attributes = {
115
- user: [:name],
116
- 'user.person' => [:first_name, :last_name, :birth_date],
117
+ user: [:name],
118
+ 'user.person' => [:first_name, :last_name, :birth_date],
117
119
  'user.person.languages' => [:name],
118
120
  categories: [:name]
119
121
  }
@@ -124,7 +126,7 @@ describe 'Query' do
124
126
  .all
125
127
  .must_equal [post]
126
128
  end
127
-
129
+
128
130
  it 'All graph attributes' do
129
131
  person = Person.new db[:people].where(document_number: 'document_2').first
130
132
 
@@ -140,6 +142,30 @@ describe 'Query' do
140
142
  .must_equal [post]
141
143
  end
142
144
 
145
+ describe 'Select computed attributes' do
146
+ it 'With join' do
147
+ db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
148
+ users_query.select_computed_attributes(:comments_count)
149
+ .where(id: 5)
150
+ .all
151
+ .must_equal [User.new(id: 5, name: 'User 5', comments_count: 2)]
152
+ end
153
+
154
+ it 'Without join' do
155
+ person_expected = Person.new user_id: 1,
156
+ document_number: 'document_1',
157
+ first_name: 'Name 1',
158
+ last_name: 'Last Name 1',
159
+ birth_date: Date.parse('2020-04-24'),
160
+ full_name: 'Name 1 Last Name 1'
161
+
162
+ people_query.select_computed_attributes(:full_name)
163
+ .where(document_number: 'document_1')
164
+ .all
165
+ .must_equal [person_expected]
166
+ end
167
+ end
168
+
143
169
  it 'Map' do
144
170
  users_query.map(&:name).must_equal db[:users].map(:name)
145
171
  end
@@ -148,45 +174,88 @@ describe 'Query' do
148
174
  users_query.detect(id: 3).must_equal User.new(id: 3, name: 'User 3')
149
175
  end
150
176
 
177
+ describe 'Each' do
178
+
179
+ it 'without size' do
180
+ users = []
181
+
182
+ users_query.each do |user|
183
+ users << user
184
+ end
185
+
186
+ users.size.must_equal 10
187
+ users.each_with_index do |user, i|
188
+ user.must_equal User.new(id: i+1, name: "User #{i+1}")
189
+ end
190
+ end
191
+
192
+ it 'with size' do
193
+ users = []
194
+ users_query.each(batch_size: 2) do |user|
195
+ users << user
196
+ end
197
+
198
+ users.size.must_equal 10
199
+ users.each_with_index do |user, i|
200
+ user.must_equal User.new(id: i+1, name: "User #{i+1}")
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ it 'Each batch' do
207
+ users_batch = []
208
+ users_query.each_batch(size: 2) do |page|
209
+ users_batch << page
210
+ end
211
+
212
+ users_batch.size.must_equal 5
213
+ i = 1
214
+ users_batch.each do |user_page|
215
+ user_page.must_equal [User.new(id: i, name: "User #{i}"), User.new(id: i+1, name: "User #{i+1}")]
216
+ i += 2
217
+ end
218
+ end
219
+
151
220
  it 'Where' do
152
221
  users_query.where(id: 3).all.must_equal [User.new(id: 3, name: 'User 3')]
153
222
  end
154
-
223
+
155
224
  it 'Exclude' do
156
225
  users_query.exclude(id: [1,2,3,4,5,6,7,8,9]).all.must_equal [User.new(id: 10, name: 'User 10')]
157
226
  end
158
-
227
+
159
228
  it 'And' do
160
229
  users_query.where(id: [1,2]).where(name: 'User 2').all.must_equal [User.new(id: 2, name: 'User 2')]
161
230
  end
162
-
231
+
163
232
  it 'Or' do
164
233
  users_query.where(id: 1).or(name: 'User 2').all.must_equal [
165
- User.new(id: 1, name: 'User 1'),
234
+ User.new(id: 1, name: 'User 1'),
166
235
  User.new(id: 2, name: 'User 2')
167
236
  ]
168
237
  end
169
-
238
+
170
239
  it 'Order' do
171
240
  posts_query.order(:title).all.must_equal [
172
- Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
173
- Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
241
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
242
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
174
243
  Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)
175
244
  ]
176
245
  end
177
-
246
+
178
247
  it 'Reverse order' do
179
248
  posts_query.reverse_order(:title).all.must_equal [
180
249
  Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1),
181
- Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
250
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
182
251
  Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)
183
252
  ]
184
253
  end
185
-
254
+
186
255
  it 'Limit and offset' do
187
256
  users_query.limit(1).offset(1).all.must_equal [User.new(id: 2, name: 'User 2')]
188
257
  end
189
-
258
+
190
259
  it 'First' do
191
260
  users_query.first.must_equal User.new(id: 1, name: 'User 1')
192
261
  end
@@ -203,21 +272,21 @@ describe 'Query' do
203
272
  language = Language.new id: 1, name: 'Spanish'
204
273
 
205
274
  person = Person.new user_id: 2,
206
- document_number: 'document_2',
207
- first_name: 'Name 2',
208
- last_name: 'Last Name 2',
275
+ document_number: 'document_2',
276
+ first_name: 'Name 2',
277
+ last_name: 'Last Name 2',
209
278
  birth_date: Date.parse('2020-04-24'),
210
279
  languages: [language]
211
280
 
212
- user = User.new id: 2,
281
+ user = User.new id: 2,
213
282
  name: 'User 2',
214
283
  person: person
215
284
 
216
- post = Post.new id: 1,
217
- user_id: 2,
285
+ post = Post.new id: 1,
286
+ user_id: 2,
218
287
  user: user,
219
- title: 'Sample post',
220
- body: '...',
288
+ title: 'Sample post',
289
+ body: '...',
221
290
  language_id: 1,
222
291
  language: language
223
292
 
@@ -237,7 +306,7 @@ describe 'Query' do
237
306
  end
238
307
 
239
308
  it 'To String' do
240
- users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#<Rasti::DB::Query: "SELECT * FROM `users` WHERE (`id` IN (1, 2, 3)) ORDER BY `name`">'
309
+ users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#<Rasti::DB::Query: "SELECT `users`.* FROM `users` WHERE (`users`.`id` IN (1, 2, 3)) ORDER BY `users`.`name`">'
241
310
  end
242
311
 
243
312
  describe 'Named queries' do
@@ -257,19 +326,19 @@ describe 'Query' do
257
326
  describe 'Join' do
258
327
 
259
328
  it 'One to Many' do
260
- users_query.join(:posts).where(title: 'Sample post').all.must_equal [User.new(id: 2, name: 'User 2')]
329
+ users_query.join(:posts).where(Sequel[:posts][:title] => 'Sample post').all.must_equal [User.new(id: 2, name: 'User 2')]
261
330
  end
262
331
 
263
332
  it 'Many to One' do
264
- posts_query.join(:user).where(name: 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1)]
333
+ posts_query.join(:user).where(Sequel[:user][:name] => 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1)]
265
334
  end
266
335
 
267
336
  it 'One to One' do
268
- users_query.join(:person).where(document_number: 'document_1').all.must_equal [User.new(id: 1, name: 'User 1')]
337
+ users_query.join(:person).where(Sequel[:person][:document_number] => 'document_1').all.must_equal [User.new(id: 1, name: 'User 1')]
269
338
  end
270
339
 
271
340
  it 'Many to Many' do
272
- posts_query.join(:categories).where(name: 'Category 3').order(:id).all.must_equal [
341
+ posts_query.join(:categories).where(Sequel[:categories][:name] => 'Category 3').order(:id).all.must_equal [
273
342
  Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
274
343
  Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
275
344
  ]
@@ -283,6 +352,20 @@ describe 'Query' do
283
352
  .must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)]
284
353
  end
285
354
 
355
+ it 'Excluded attributes permanents excluded when join' do
356
+ posts_query.join(:user)
357
+ .exclude_attributes(:body)
358
+ .where(Sequel[:user][:name] => 'User 4')
359
+ .all
360
+ .must_equal [Post.new(id: 3, title: 'Best post', user_id: 4, language_id: 1)]
361
+
362
+ posts_query.exclude_attributes(:body)
363
+ .join(:user)
364
+ .where(Sequel[:user][:name] => 'User 4')
365
+ .all
366
+ .must_equal [Post.new(id: 3, title: 'Best post', user_id: 4, language_id: 1)]
367
+ end
368
+
286
369
  describe 'Multiple data sources' do
287
370
 
288
371
  it 'One to Many' do
@@ -309,7 +392,7 @@ describe 'Query' do
309
392
  error = proc { posts_query.nql('a + b') }.must_raise Rasti::DB::NQL::InvalidExpressionError
310
393
  error.message.must_equal 'Invalid filter expression: a + b'
311
394
  end
312
-
395
+
313
396
  it 'Filter to self table' do
314
397
  posts_query.nql('user_id > 1')
315
398
  .pluck(:user_id)
@@ -336,6 +419,138 @@ describe 'Query' do
336
419
  .must_equal [2]
337
420
  end
338
421
 
422
+ describe 'Computed Attributes' do
423
+
424
+ it 'Filter relation computed attribute' do
425
+ db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
426
+ users_query.nql('comments_count = 2').all.must_equal [User.new(id: 5, name: 'User 5')]
427
+ end
428
+
429
+ it 'Filter with relation computed attribute with "and" combined' do
430
+ db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
431
+ db[:comments].insert post_id: 1, user_id: 4, text: 'Comment 3'
432
+ users_query.nql('(comments_count > 1) & (id = 5)').all.must_equal [User.new(id: 5, name: 'User 5')]
433
+ end
434
+
435
+ it 'Filter relation computed attribute with "or" combined' do
436
+ db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
437
+ users_query.nql('(comments_count = 2) | (id = 5)')
438
+ .order(:id)
439
+ .all
440
+ .must_equal [ User.new(id: 2, name: 'User 2'), User.new(id: 5, name: 'User 5') ]
441
+ end
442
+
443
+ it 'Filter relation computed attribute with "and" and "or" combined' do
444
+ db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
445
+ users_query.nql('((comments_count = 2) | (id = 5)) & (name: User 5)')
446
+ .order(:id)
447
+ .all
448
+ .must_equal [ User.new(id: 5, name: 'User 5') ]
449
+ end
450
+
451
+ it 'Filter simple computed attribute' do
452
+ person_expected = Person.new user_id: 1,
453
+ document_number: 'document_1',
454
+ first_name: 'Name 1',
455
+ last_name: 'Last Name 1',
456
+ birth_date: Date.parse('2020-04-24')
457
+
458
+ people_query.nql('full_name = Name 1 Last Name 1')
459
+ .all
460
+ .must_equal [person_expected]
461
+ end
462
+
463
+ end
464
+
465
+ describe 'Filter Array' do
466
+
467
+ def filter_condition_must_raise(comparison_symbol, comparison_name)
468
+ error = proc { comments_query.nql("tags #{comparison_symbol} [fake, notice]") }.must_raise Rasti::DB::NQL::FilterConditionStrategies::UnsupportedTypeComparison
469
+ error.argument_type.must_equal Rasti::DB::NQL::FilterConditionStrategies::Types::SQLiteArray
470
+ error.comparison_name.must_equal comparison_name
471
+ error.message.must_equal "Unsupported comparison #{comparison_name} for Rasti::DB::NQL::FilterConditionStrategies::Types::SQLiteArray"
472
+ end
473
+
474
+ it 'Must raise exception from not supported methods' do
475
+ comparisons = {
476
+ greater_than: '>',
477
+ greater_than_or_equal: '>=',
478
+ less_than: '<',
479
+ less_than_or_equal: '<='
480
+ }
481
+
482
+ comparisons.each do |name, symbol|
483
+ filter_condition_must_raise symbol, name
484
+ end
485
+ end
486
+
487
+ it 'Included any of these elements' do
488
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
489
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 2', tags: '["notice"]'
490
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 3', tags: '["fake_notice"]'
491
+ expected_comments = [
492
+ Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1),
493
+ Comment.new(id: 5, text: 'fake notice 2', tags: ['notice'], user_id: 5, post_id: 1)
494
+ ]
495
+
496
+ comments_query.nql('tags: [ fake, notice ]')
497
+ .all
498
+ .must_equal expected_comments
499
+ end
500
+
501
+ it 'Included exactly all these elements' do
502
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
503
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 2', tags: '["notice"]'
504
+ comments_query.nql('tags = [fake, notice]')
505
+ .all
506
+ .must_equal [Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1)]
507
+ end
508
+
509
+ it 'Not included anyone of these elements' do
510
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
511
+ db[:comments].insert post_id: 1, user_id: 5, text: 'Good notice!', tags: '["good"]'
512
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake"]'
513
+ expected_comments = [
514
+ Comment.new(id: 1, text: 'Comment 1', tags: [], user_id: 5, post_id: 1),
515
+ Comment.new(id: 2, text: 'Comment 2', tags: [], user_id: 7, post_id: 1),
516
+ Comment.new(id: 3, text: 'Comment 3', tags: [], user_id: 2, post_id: 2),
517
+ Comment.new(id: 5, text: 'Good notice!', tags: ['good'], user_id: 5, post_id: 1)
518
+ ]
519
+ comments_query.nql('tags !: [fake, notice]')
520
+ .all
521
+ .must_equal expected_comments
522
+ end
523
+
524
+ it 'Not include any of these elements' do
525
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
526
+ db[:comments].insert post_id: 1, user_id: 5, text: 'Good notice!', tags: '["good"]'
527
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake"]'
528
+ expected_comments = [
529
+ Comment.new(id: 1, text: 'Comment 1', tags: '[]', user_id: 5, post_id: 1),
530
+ Comment.new(id: 2, text: 'Comment 2', tags: '[]', user_id: 7, post_id: 1),
531
+ Comment.new(id: 3, text: 'Comment 3', tags: '[]', user_id: 2, post_id: 2),
532
+ Comment.new(id: 5, text: 'Good notice!', tags: ['good'], user_id: 5, post_id: 1),
533
+ Comment.new(id: 6, text: 'fake notice', tags: ['fake'], user_id: 5, post_id: 1)
534
+ ]
535
+ comments_query.nql('tags != [fake, notice]')
536
+ .all
537
+ .must_equal expected_comments
538
+ end
539
+
540
+ it 'Include any like these elements' do
541
+ db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
542
+ db[:comments].insert post_id: 1, user_id: 5, text: 'this is a fake notice!', tags: '["fake_notice"]'
543
+ expected_comments = [
544
+ Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1),
545
+ Comment.new(id: 5, text: 'this is a fake notice!', tags: ['fake_notice'], user_id: 5, post_id: 1)
546
+ ]
547
+ comments_query.nql('tags ~ [fake]')
548
+ .all
549
+ .must_equal expected_comments
550
+ end
551
+
552
+ end
553
+
339
554
  end
340
555
 
341
556
  end