mongoid 7.2.6 → 7.3.3

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 (154) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Rakefile +16 -0
  4. data/lib/config/locales/en.yml +2 -2
  5. data/lib/mongoid/association/accessors.rb +13 -1
  6. data/lib/mongoid/association/constrainable.rb +1 -1
  7. data/lib/mongoid/association/depending.rb +4 -4
  8. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  9. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  10. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  11. data/lib/mongoid/association/nested/many.rb +1 -1
  12. data/lib/mongoid/association/nested/one.rb +4 -2
  13. data/lib/mongoid/association/proxy.rb +6 -1
  14. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  15. data/lib/mongoid/association/referenced/has_many/enumerable.rb +490 -496
  16. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  17. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  18. data/lib/mongoid/atomic.rb +26 -2
  19. data/lib/mongoid/attributes/projector.rb +120 -0
  20. data/lib/mongoid/attributes.rb +24 -13
  21. data/lib/mongoid/cacheable.rb +2 -2
  22. data/lib/mongoid/clients/factory.rb +22 -8
  23. data/lib/mongoid/clients.rb +1 -1
  24. data/lib/mongoid/config.rb +19 -2
  25. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  26. data/lib/mongoid/copyable.rb +1 -1
  27. data/lib/mongoid/criteria/findable.rb +1 -1
  28. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  29. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  30. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  31. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  32. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  33. data/lib/mongoid/criteria.rb +4 -5
  34. data/lib/mongoid/document.rb +1 -15
  35. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  36. data/lib/mongoid/evolvable.rb +1 -1
  37. data/lib/mongoid/extensions/boolean.rb +1 -2
  38. data/lib/mongoid/extensions/false_class.rb +1 -1
  39. data/lib/mongoid/extensions/hash.rb +2 -2
  40. data/lib/mongoid/extensions/true_class.rb +1 -1
  41. data/lib/mongoid/fields.rb +43 -5
  42. data/lib/mongoid/inspectable.rb +1 -1
  43. data/lib/mongoid/matcher/bits.rb +41 -0
  44. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  45. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  46. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  47. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  48. data/lib/mongoid/matcher/expression.rb +4 -0
  49. data/lib/mongoid/matcher/field_operator.rb +6 -0
  50. data/lib/mongoid/matcher/mod.rb +17 -0
  51. data/lib/mongoid/matcher/type.rb +99 -0
  52. data/lib/mongoid/matcher.rb +7 -0
  53. data/lib/mongoid/persistable/deletable.rb +1 -2
  54. data/lib/mongoid/persistable/destroyable.rb +8 -2
  55. data/lib/mongoid/persistable/updatable.rb +27 -2
  56. data/lib/mongoid/query_cache.rb +35 -29
  57. data/lib/mongoid/selectable.rb +5 -7
  58. data/lib/mongoid/shardable.rb +21 -5
  59. data/lib/mongoid/touchable.rb +33 -4
  60. data/lib/mongoid/version.rb +1 -1
  61. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  62. data/spec/integration/associations/has_one_spec.rb +48 -0
  63. data/spec/integration/criteria/date_field_spec.rb +1 -1
  64. data/spec/integration/document_spec.rb +9 -0
  65. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  66. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  67. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  68. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  69. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  70. data/spec/integration/matcher_operator_data/in.yml +16 -0
  71. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  72. data/spec/integration/matcher_operator_data/type.yml +70 -0
  73. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  74. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  75. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  76. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  77. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  78. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  79. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  80. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  81. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  82. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  83. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  84. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  85. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  86. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  87. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  88. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  89. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  90. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  91. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  92. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  93. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  94. data/spec/lite_spec_helper.rb +2 -0
  95. data/spec/mongoid/association/depending_spec.rb +391 -352
  96. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  97. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  98. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  99. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  100. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +245 -93
  101. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +6 -6
  102. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  103. data/spec/mongoid/atomic/paths_spec.rb +64 -12
  104. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  105. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  106. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  107. data/spec/mongoid/attributes_spec.rb +98 -6
  108. data/spec/mongoid/clients/factory_spec.rb +48 -0
  109. data/spec/mongoid/config_spec.rb +106 -1
  110. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  111. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  112. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  113. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  114. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  115. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
  116. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  117. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  118. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  119. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  120. data/spec/mongoid/criteria_spec.rb +0 -275
  121. data/spec/mongoid/document_spec.rb +13 -13
  122. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  123. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  124. data/spec/mongoid/extensions/string_spec.rb +5 -5
  125. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  126. data/spec/mongoid/fields/localized_spec.rb +4 -4
  127. data/spec/mongoid/fields_spec.rb +4 -4
  128. data/spec/mongoid/inspectable_spec.rb +12 -4
  129. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  130. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  131. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  132. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  133. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  134. data/spec/mongoid/reloadable_spec.rb +18 -1
  135. data/spec/mongoid/shardable_spec.rb +44 -0
  136. data/spec/mongoid/touchable_spec.rb +122 -16
  137. data/spec/mongoid/touchable_spec_models.rb +54 -0
  138. data/spec/mongoid/validatable_spec.rb +1 -1
  139. data/spec/spec_helper.rb +6 -2
  140. data/spec/support/client_registry.rb +9 -0
  141. data/spec/support/models/bolt.rb +8 -0
  142. data/spec/support/models/hole.rb +13 -0
  143. data/spec/support/models/mop.rb +0 -1
  144. data/spec/support/models/nut.rb +8 -0
  145. data/spec/support/models/person.rb +6 -0
  146. data/spec/support/models/sealer.rb +8 -0
  147. data/spec/support/models/shirt.rb +12 -0
  148. data/spec/support/models/spacer.rb +8 -0
  149. data/spec/support/models/threadlocker.rb +8 -0
  150. data/spec/support/models/washer.rb +8 -0
  151. data.tar.gz.sig +0 -0
  152. metadata +97 -3
  153. metadata.gz.sig +0 -0
  154. data/spec/support/cluster_config.rb +0 -158
@@ -417,6 +417,40 @@ describe Mongoid::Criteria::Queryable::Selectable do
417
417
  it_behaves_like 'returns a cloned query'
418
418
  end
419
419
 
420
+ context 'when criteria use operators' do
421
+ shared_examples 'behave correctly' do
422
+ let(:selection) do
423
+ query.and(
424
+ { field: {first_operator => [ 1, 2 ] }},
425
+ { field: {second_operator => [ 3, 4 ] }},
426
+ )
427
+ end
428
+
429
+ it "combines via $and operator and stringifies all keys" do
430
+ expect(selection.selector).to eq({
431
+ "field" => {'$in' => [ 1, 2 ]},
432
+ "$and" => [
433
+ { "field" => {'$in' => [ 3, 4 ] }}
434
+ ]
435
+ })
436
+ end
437
+ end
438
+
439
+ [
440
+ ['$in', '$in'],
441
+ [:$in, '$in'],
442
+ ['$in', :$in],
443
+ [:$in, :$in],
444
+ ].each do |first_operator, second_operator|
445
+ context "when first operator is #{first_operator.inspect} and second operator is #{second_operator.inspect}" do
446
+ let(:first_operator) { first_operator }
447
+ let(:second_operator) { second_operator }
448
+
449
+ include_examples 'behave correctly'
450
+ end
451
+ end
452
+ end
453
+
420
454
  context 'when criteria are handled via Key' do
421
455
  shared_examples_for 'adds the conditions to top level' do
422
456
 
@@ -467,12 +501,44 @@ describe Mongoid::Criteria::Queryable::Selectable do
467
501
  it_behaves_like 'returns a cloned query'
468
502
  end
469
503
 
504
+ shared_examples_for 'combines conditions with $eq' do
505
+
506
+ it "combines conditions with $eq" do
507
+ expect(selection.selector).to eq({
508
+ "field" => {'$eq' => 3, '$lt' => 5},
509
+ })
510
+ end
511
+
512
+ it_behaves_like 'returns a cloned query'
513
+ end
514
+
515
+ shared_examples_for 'combines conditions with $regex' do
516
+
517
+ it "combines conditions with $regex" do
518
+ expect(selection.selector).to eq({
519
+ "field" => {'$regex' => /t/, '$lt' => 5},
520
+ })
521
+ end
522
+
523
+ it_behaves_like 'returns a cloned query'
524
+ end
525
+
470
526
  context 'criteria are provided in the same hash' do
471
- let(:selection) do
472
- query.send(tested_method, :field => 3, :field.lt => 5)
527
+ context 'non-regexp argument' do
528
+ let(:selection) do
529
+ query.send(tested_method, :field => 3, :field.lt => 5)
530
+ end
531
+
532
+ it_behaves_like 'combines conditions with $eq'
473
533
  end
474
534
 
475
- it_behaves_like 'combines conditions with $and'
535
+ context 'regexp argument' do
536
+ let(:selection) do
537
+ query.send(tested_method, :field => /t/, :field.lt => 5)
538
+ end
539
+
540
+ it_behaves_like 'combines conditions with $regex'
541
+ end
476
542
  end
477
543
 
478
544
  context 'criteria are provided in separate hashes' do
@@ -505,12 +571,44 @@ describe Mongoid::Criteria::Queryable::Selectable do
505
571
  it_behaves_like 'returns a cloned query'
506
572
  end
507
573
 
574
+ shared_examples_for 'combines conditions with $eq' do
575
+
576
+ it "combines conditions with $eq" do
577
+ expect(selection.selector).to eq({
578
+ "field" => {'$gt' => 3, '$eq' => 5},
579
+ })
580
+ end
581
+
582
+ it_behaves_like 'returns a cloned query'
583
+ end
584
+
585
+ shared_examples_for 'combines conditions with $regex' do
586
+
587
+ it "combines conditions with $regex" do
588
+ expect(selection.selector).to eq({
589
+ "field" => {'$gt' => 3, '$regex' => /t/},
590
+ })
591
+ end
592
+
593
+ it_behaves_like 'returns a cloned query'
594
+ end
595
+
508
596
  context 'criteria are provided in the same hash' do
509
- let(:selection) do
510
- query.send(tested_method, :field.gt => 3, :field => 5)
597
+ context 'non-regexp argument' do
598
+ let(:selection) do
599
+ query.send(tested_method, :field.gt => 3, :field => 5)
600
+ end
601
+
602
+ it_behaves_like 'combines conditions with $eq'
511
603
  end
512
604
 
513
- it_behaves_like 'combines conditions with $and'
605
+ context 'regexp argument' do
606
+ let(:selection) do
607
+ query.send(tested_method, :field.gt => 3, :field => /t/)
608
+ end
609
+
610
+ it_behaves_like 'combines conditions with $regex'
611
+ end
514
612
  end
515
613
 
516
614
  context 'criteria are provided in separate hashes' do
@@ -1031,6 +1129,38 @@ describe Mongoid::Criteria::Queryable::Selectable do
1031
1129
  end
1032
1130
  end
1033
1131
  end
1132
+
1133
+ context 'when giving multiple conditions in one call on the same key with symbol operator' do
1134
+
1135
+ context 'non-regexp argument' do
1136
+ let(:selection) do
1137
+ query.send(tested_method, field: 1, :field.gt => 0)
1138
+ end
1139
+
1140
+ it 'combines conditions with $eq' do
1141
+ selection.selector.should == {
1142
+ expected_operator => [
1143
+ 'field' => {'$eq' => 1, '$gt' => 0},
1144
+ ]
1145
+ }
1146
+ end
1147
+ end
1148
+
1149
+ context 'regexp argument' do
1150
+ let(:selection) do
1151
+ query.send(tested_method, field: /t/, :field.gt => 0)
1152
+ end
1153
+
1154
+ it 'combines conditions with $regex' do
1155
+ selection.selector.should == {
1156
+ expected_operator => [
1157
+ 'field' => {'$regex' => /t/, '$gt' => 0},
1158
+ ]
1159
+ }
1160
+ end
1161
+ end
1162
+
1163
+ end
1034
1164
  end
1035
1165
 
1036
1166
  describe "#or" do
@@ -1270,14 +1400,28 @@ describe Mongoid::Criteria::Queryable::Selectable do
1270
1400
  it_behaves_like 'returns a cloned query'
1271
1401
  end
1272
1402
 
1273
- shared_examples_for 'adds one condition' do
1403
+ shared_examples_for 'combines conditions with $eq' do
1274
1404
 
1275
- it "adds one condition" do
1405
+ it "combines conditions with $eq" do
1276
1406
  expect(selection.selector).to eq({
1277
- 'field' => 3,
1278
- '$and' => [
1279
- {'field' => {'$lt' => 5}},
1280
- ],
1407
+ 'field' => {
1408
+ '$eq' => 3,
1409
+ '$lt' => 5,
1410
+ },
1411
+ })
1412
+ end
1413
+
1414
+ it_behaves_like 'returns a cloned query'
1415
+ end
1416
+
1417
+ shared_examples_for 'combines conditions with $regex' do
1418
+
1419
+ it "combines conditions with $regex" do
1420
+ expect(selection.selector).to eq({
1421
+ 'field' => {
1422
+ '$regex' => /t/,
1423
+ '$lt' => 5,
1424
+ },
1281
1425
  })
1282
1426
  end
1283
1427
 
@@ -1285,11 +1429,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
1285
1429
  end
1286
1430
 
1287
1431
  context 'criteria are provided in the same hash' do
1288
- let(:selection) do
1289
- query.send(tested_method, :field => 3, :field.lt => 5)
1432
+ context 'non-regexp argument' do
1433
+ let(:selection) do
1434
+ query.send(tested_method, :field => 3, :field.lt => 5)
1435
+ end
1436
+
1437
+ it_behaves_like 'combines conditions with $eq'
1290
1438
  end
1291
1439
 
1292
- it_behaves_like 'adds one condition'
1440
+ context 'regexp argument' do
1441
+ let(:selection) do
1442
+ query.send(tested_method, :field => /t/, :field.lt => 5)
1443
+ end
1444
+
1445
+ it_behaves_like 'combines conditions with $regex'
1446
+ end
1293
1447
  end
1294
1448
 
1295
1449
  context 'criteria are provided in separate hashes' do
@@ -1324,24 +1478,44 @@ describe Mongoid::Criteria::Queryable::Selectable do
1324
1478
  it_behaves_like 'returns a cloned query'
1325
1479
  end
1326
1480
 
1327
- shared_examples_for 'adds one condition' do
1481
+ shared_examples_for 'combines conditions with $eq' do
1328
1482
 
1329
- it "adds one condition" do
1330
- expect(selection.selector).to eq({
1331
- 'field' => {'$gt' => 3},
1332
- '$and' => ['field' => 5],
1333
- })
1483
+ it "combines conditions with $eq" do
1484
+ expect(selection.selector).to eq(
1485
+ 'field' => {'$gt' => 3, '$eq' => 5},
1486
+ )
1487
+ end
1488
+
1489
+ it_behaves_like 'returns a cloned query'
1490
+ end
1491
+
1492
+ shared_examples_for 'combines conditions with $regex' do
1493
+
1494
+ it "combines conditions with $regex" do
1495
+ expect(selection.selector).to eq(
1496
+ 'field' => {'$gt' => 3, '$regex' => /t/},
1497
+ )
1334
1498
  end
1335
1499
 
1336
1500
  it_behaves_like 'returns a cloned query'
1337
1501
  end
1338
1502
 
1339
1503
  context 'criteria are provided in the same hash' do
1340
- let(:selection) do
1341
- query.send(tested_method, :field.gt => 3, :field => 5)
1504
+ context 'non-regexp argument' do
1505
+ let(:selection) do
1506
+ query.send(tested_method, :field.gt => 3, :field => 5)
1507
+ end
1508
+
1509
+ it_behaves_like 'combines conditions with $eq'
1342
1510
  end
1343
1511
 
1344
- it_behaves_like 'adds one condition'
1512
+ context 'regexp argument' do
1513
+ let(:selection) do
1514
+ query.send(tested_method, :field.gt => 3, :field => /t/)
1515
+ end
1516
+
1517
+ it_behaves_like 'combines conditions with $regex'
1518
+ end
1345
1519
  end
1346
1520
 
1347
1521
  context 'criteria are provided in separate hashes' do
@@ -1861,5 +2035,36 @@ describe Mongoid::Criteria::Queryable::Selectable do
1861
2035
  )
1862
2036
  end
1863
2037
  end
2038
+
2039
+ context 'when giving multiple conditions in one call on the same key with symbol operator' do
2040
+
2041
+ context 'non-regexp argument' do
2042
+ let(:selection) do
2043
+ query.not(field: 1, :field.gt => 0)
2044
+ end
2045
+
2046
+ it 'combines conditions with $eq' do
2047
+ selection.selector.should == {
2048
+ '$and' => ['$nor' => [
2049
+ 'field' => {'$eq' => 1, '$gt' => 0},
2050
+ ]]
2051
+ }
2052
+ end
2053
+ end
2054
+
2055
+ context 'regexp argument' do
2056
+ let(:selection) do
2057
+ query.not(field: /t/, :field.gt => 0)
2058
+ end
2059
+
2060
+ it 'combines conditions with $regex' do
2061
+ selection.selector.should == {
2062
+ '$and' => ['$nor' => [
2063
+ 'field' => {'$regex' => /t/, '$gt' => 0},
2064
+ ]]
2065
+ }
2066
+ end
2067
+ end
2068
+ end
1864
2069
  end
1865
2070
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ shared_examples_for "returns a cloned query" do
5
+
6
+ it "returns a cloned query" do
7
+ expect(selection).to_not equal(query)
8
+ end
9
+ end
10
+
11
+ shared_examples_for 'requires an argument' do
12
+ context "when provided no argument" do
13
+
14
+ let(:selection) do
15
+ query.send(query_method)
16
+ end
17
+
18
+ it "raises ArgumentError" do
19
+ expect do
20
+ selection.selector
21
+ end.to raise_error(ArgumentError)
22
+ end
23
+ end
24
+ end
25
+
26
+ shared_examples_for 'requires a non-nil argument' do
27
+ context "when provided nil" do
28
+
29
+ let(:selection) do
30
+ query.send(query_method, nil)
31
+ end
32
+
33
+ it "raises CriteriaArgumentRequired" do
34
+ expect do
35
+ selection.selector
36
+ end.to raise_error(Mongoid::Errors::CriteriaArgumentRequired, /#{query_method}/)
37
+ end
38
+ end
39
+ end
@@ -2,6 +2,7 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  require "spec_helper"
5
+ require_relative './selectable_shared_examples'
5
6
 
6
7
  class FieldWithSerializer
7
8
  def evolve(object)
@@ -19,43 +20,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
19
20
  Mongoid::Query.new("id" => "_id")
20
21
  end
21
22
 
22
- shared_examples_for "returns a cloned query" do
23
-
24
- it "returns a cloned query" do
25
- expect(selection).to_not equal(query)
26
- end
27
- end
28
-
29
- shared_examples_for 'requires an argument' do
30
- context "when provided no argument" do
31
-
32
- let(:selection) do
33
- query.send(query_method)
34
- end
35
-
36
- it "raises ArgumentError" do
37
- expect do
38
- selection.selector
39
- end.to raise_error(ArgumentError)
40
- end
41
- end
42
- end
43
-
44
- shared_examples_for 'requires a non-nil argument' do
45
- context "when provided nil" do
46
-
47
- let(:selection) do
48
- query.send(query_method, nil)
49
- end
50
-
51
- it "raises CriteriaArgumentRequired" do
52
- expect do
53
- selection.selector
54
- end.to raise_error(Mongoid::Errors::CriteriaArgumentRequired, /#{query_method}/)
55
- end
56
- end
57
- end
58
-
59
23
  shared_examples_for 'supports merge strategies' do
60
24
 
61
25
  context 'when the field is not aliased' do
@@ -1978,534 +1942,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
1978
1942
  end
1979
1943
  end
1980
1944
 
1981
- describe "#where" do
1982
-
1983
- let(:query_method) { :where }
1984
-
1985
- context "when provided no criterion" do
1986
-
1987
- let(:selection) do
1988
- query.where
1989
- end
1990
-
1991
- it "does not add any criterion" do
1992
- expect(selection.selector).to eq({})
1993
- end
1994
-
1995
- it "returns the query" do
1996
- expect(selection).to eq(query)
1997
- end
1998
-
1999
- it "returns a cloned query" do
2000
- expect(selection).to_not equal(query)
2001
- end
2002
- end
2003
-
2004
- it_behaves_like 'requires a non-nil argument'
2005
-
2006
- context "when provided a string" do
2007
-
2008
- let(:selection) do
2009
- query.where("this.value = 10")
2010
- end
2011
-
2012
- it "adds the $where criterion" do
2013
- expect(selection.selector).to eq({ "$where" => "this.value = 10" })
2014
- end
2015
-
2016
- it "returns a cloned query" do
2017
- expect(selection).to_not equal(query)
2018
- end
2019
-
2020
- context 'when multiple calls with string argument are made' do
2021
-
2022
- let(:selection) do
2023
- query.where("this.value = 10").where('foo.bar')
2024
- end
2025
-
2026
- it 'combines conditions' do
2027
- expect(selection.selector).to eq(
2028
- "$where" => "this.value = 10", '$and' => [{'$where' => 'foo.bar'}],
2029
- )
2030
- end
2031
- end
2032
-
2033
- context 'when called with string argument and with hash argument' do
2034
-
2035
- let(:selection) do
2036
- query.where("this.value = 10").where(foo: 'bar')
2037
- end
2038
-
2039
- it 'combines conditions' do
2040
- expect(selection.selector).to eq(
2041
- "$where" => "this.value = 10", 'foo' => 'bar',
2042
- )
2043
- end
2044
- end
2045
-
2046
- context 'when called with hash argument and with string argument' do
2047
-
2048
- let(:selection) do
2049
- query.where(foo: 'bar').where("this.value = 10")
2050
- end
2051
-
2052
- it 'combines conditions' do
2053
- expect(selection.selector).to eq(
2054
- 'foo' => 'bar', "$where" => "this.value = 10",
2055
- )
2056
- end
2057
- end
2058
- end
2059
-
2060
- context "when provided a single criterion" do
2061
-
2062
- context "when the value needs no evolution" do
2063
-
2064
- let(:selection) do
2065
- query.where(name: "Syd")
2066
- end
2067
-
2068
- it "adds the criterion to the selection" do
2069
- expect(selection.selector).to eq({ "name" => "Syd" })
2070
- end
2071
- end
2072
-
2073
- context "when the value must be evolved" do
2074
-
2075
- before(:all) do
2076
- class Document
2077
- def id
2078
- 13
2079
- end
2080
- def self.evolve(object)
2081
- object.id
2082
- end
2083
- end
2084
- end
2085
-
2086
- after(:all) do
2087
- Object.send(:remove_const, :Document)
2088
- end
2089
-
2090
- context "when the key needs evolution" do
2091
-
2092
- let(:query) do
2093
- Mongoid::Query.new({ "user" => "user_id" })
2094
- end
2095
-
2096
- let(:document) do
2097
- Document.new
2098
- end
2099
-
2100
- let(:selection) do
2101
- query.where(user: document)
2102
- end
2103
-
2104
- it "alters the key and value" do
2105
- expect(selection.selector).to eq({ "user_id" => document.id })
2106
- end
2107
- end
2108
-
2109
- context 'when the field is a String and the value is a BSON::Regexp::Raw' do
2110
-
2111
- let(:raw_regexp) do
2112
- BSON::Regexp::Raw.new('^Em')
2113
- end
2114
-
2115
- let(:selection) do
2116
- Login.where(_id: raw_regexp)
2117
- end
2118
-
2119
- it 'does not convert the bson raw regexp object to a String' do
2120
- expect(selection.selector).to eq({ "_id" => raw_regexp })
2121
- end
2122
- end
2123
- end
2124
- end
2125
-
2126
- context "when provided complex criterion" do
2127
-
2128
- context "when performing an $all" do
2129
-
2130
- context "when performing a single query" do
2131
-
2132
- let(:selection) do
2133
- query.where(:field.all => [ 1, 2 ])
2134
- end
2135
-
2136
- it "adds the $all criterion" do
2137
- expect(selection.selector).to eq({ "field" => { "$all" => [ 1, 2 ] }})
2138
- end
2139
-
2140
- it "returns a cloned query" do
2141
- expect(selection).to_not eq(query)
2142
- end
2143
- end
2144
- end
2145
-
2146
- context "when performing an $elemMatch" do
2147
-
2148
- context "when the value is not complex" do
2149
-
2150
- let(:selection) do
2151
- query.where(:field.elem_match => { key: 1 })
2152
- end
2153
-
2154
- it "adds the $elemMatch criterion" do
2155
- expect(selection.selector).to eq(
2156
- { "field" => { "$elemMatch" => { key: 1 } }}
2157
- )
2158
- end
2159
-
2160
- it "returns a cloned query" do
2161
- expect(selection).to_not eq(query)
2162
- end
2163
- end
2164
-
2165
- context "when the value is complex" do
2166
-
2167
- let(:selection) do
2168
- query.where(:field.elem_match => { :key.gt => 1 })
2169
- end
2170
-
2171
- it "adds the $elemMatch criterion" do
2172
- expect(selection.selector).to eq(
2173
- { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
2174
- )
2175
- end
2176
-
2177
- it "returns a cloned query" do
2178
- expect(selection).to_not eq(query)
2179
- end
2180
- end
2181
- end
2182
-
2183
- context "when performing an $exists" do
2184
-
2185
- context "when providing boolean values" do
2186
-
2187
- let(:selection) do
2188
- query.where(:field.exists => true)
2189
- end
2190
-
2191
- it "adds the $exists criterion" do
2192
- expect(selection.selector).to eq(
2193
- { "field" => { "$exists" => true }}
2194
- )
2195
- end
2196
-
2197
- it "returns a cloned query" do
2198
- expect(selection).to_not eq(query)
2199
- end
2200
- end
2201
-
2202
- context "when providing string values" do
2203
-
2204
- let(:selection) do
2205
- query.where(:field.exists => "t")
2206
- end
2207
-
2208
- it "adds the $exists criterion" do
2209
- expect(selection.selector).to eq(
2210
- { "field" => { "$exists" => true }}
2211
- )
2212
- end
2213
-
2214
- it "returns a cloned query" do
2215
- expect(selection).to_not eq(query)
2216
- end
2217
- end
2218
- end
2219
-
2220
- context "when performing a $gt" do
2221
-
2222
- let(:selection) do
2223
- query.where(:field.gt => 10)
2224
- end
2225
-
2226
- it "adds the $gt criterion" do
2227
- expect(selection.selector).to eq(
2228
- { "field" => { "$gt" => 10 }}
2229
- )
2230
- end
2231
-
2232
- it "returns a cloned query" do
2233
- expect(selection).to_not eq(query)
2234
- end
2235
- end
2236
-
2237
- context "when performing a $gte" do
2238
-
2239
- let(:selection) do
2240
- query.where(:field.gte => 10)
2241
- end
2242
-
2243
- it "adds the $gte criterion" do
2244
- expect(selection.selector).to eq(
2245
- { "field" => { "$gte" => 10 }}
2246
- )
2247
- end
2248
-
2249
- it "returns a cloned query" do
2250
- expect(selection).to_not eq(query)
2251
- end
2252
- end
2253
-
2254
- context "when performing an $in" do
2255
-
2256
- let(:selection) do
2257
- query.where(:field.in => [ 1, 2 ])
2258
- end
2259
-
2260
- it "adds the $in criterion" do
2261
- expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
2262
- end
2263
-
2264
- it "returns a cloned query" do
2265
- expect(selection).to_not eq(query)
2266
- end
2267
- end
2268
-
2269
- context "when performing a $lt" do
2270
-
2271
- let(:selection) do
2272
- query.where(:field.lt => 10)
2273
- end
2274
-
2275
- it "adds the $lt criterion" do
2276
- expect(selection.selector).to eq(
2277
- { "field" => { "$lt" => 10 }}
2278
- )
2279
- end
2280
-
2281
- it "returns a cloned query" do
2282
- expect(selection).to_not eq(query)
2283
- end
2284
- end
2285
-
2286
- context "when performing a $lte" do
2287
-
2288
- let(:selection) do
2289
- query.where(:field.lte => 10)
2290
- end
2291
-
2292
- it "adds the $lte criterion" do
2293
- expect(selection.selector).to eq(
2294
- { "field" => { "$lte" => 10 }}
2295
- )
2296
- end
2297
-
2298
- it "returns a cloned query" do
2299
- expect(selection).to_not eq(query)
2300
- end
2301
- end
2302
-
2303
- context "when performing a $mod" do
2304
-
2305
- let(:selection) do
2306
- query.where(:field.mod => [ 10, 1 ])
2307
- end
2308
-
2309
- it "adds the $lte criterion" do
2310
- expect(selection.selector).to eq(
2311
- { "field" => { "$mod" => [ 10, 1 ]}}
2312
- )
2313
- end
2314
-
2315
- it "returns a cloned query" do
2316
- expect(selection).to_not eq(query)
2317
- end
2318
- end
2319
-
2320
- context "when performing a $ne" do
2321
-
2322
- let(:selection) do
2323
- query.where(:field.ne => 10)
2324
- end
2325
-
2326
- it "adds the $ne criterion" do
2327
- expect(selection.selector).to eq(
2328
- { "field" => { "$ne" => 10 }}
2329
- )
2330
- end
2331
-
2332
- it "returns a cloned query" do
2333
- expect(selection).to_not eq(query)
2334
- end
2335
- end
2336
-
2337
- context "when performing a $near" do
2338
-
2339
- let(:selection) do
2340
- query.where(:field.near => [ 1, 1 ])
2341
- end
2342
-
2343
- it "adds the $near criterion" do
2344
- expect(selection.selector).to eq(
2345
- { "field" => { "$near" => [ 1, 1 ] }}
2346
- )
2347
- end
2348
-
2349
- it "returns a cloned query" do
2350
- expect(selection).to_not eq(query)
2351
- end
2352
- end
2353
-
2354
- context "when performing a $nearSphere" do
2355
-
2356
- let(:selection) do
2357
- query.where(:field.near_sphere => [ 1, 1 ])
2358
- end
2359
-
2360
- it "adds the $nearSphere criterion" do
2361
- expect(selection.selector).to eq(
2362
- { "field" => { "$nearSphere" => [ 1, 1 ] }}
2363
- )
2364
- end
2365
-
2366
- it "returns a cloned query" do
2367
- expect(selection).to_not eq(query)
2368
- end
2369
- end
2370
-
2371
- context "when performing a $nin" do
2372
-
2373
- let(:selection) do
2374
- query.where(:field.nin => [ 1, 2 ])
2375
- end
2376
-
2377
- it "adds the $nin criterion" do
2378
- expect(selection.selector).to eq({ "field" => { "$nin" => [ 1, 2 ] }})
2379
- end
2380
-
2381
- it "returns a cloned query" do
2382
- expect(selection).to_not eq(query)
2383
- end
2384
- end
2385
-
2386
- context "when performing a $not" do
2387
-
2388
- let(:selection) do
2389
- query.where(:field.not => /test/)
2390
- end
2391
-
2392
- it "adds the $not criterion" do
2393
- expect(selection.selector).to eq({ "field" => { "$not" => /test/ }})
2394
- end
2395
-
2396
- it "returns a cloned query" do
2397
- expect(selection).to_not eq(query)
2398
- end
2399
- end
2400
-
2401
- context "when performing a $size" do
2402
-
2403
- context "when providing an integer" do
2404
-
2405
- let(:selection) do
2406
- query.where(:field.with_size => 10)
2407
- end
2408
-
2409
- it "adds the $size criterion" do
2410
- expect(selection.selector).to eq(
2411
- { "field" => { "$size" => 10 }}
2412
- )
2413
- end
2414
-
2415
- it "returns a cloned query" do
2416
- expect(selection).to_not eq(query)
2417
- end
2418
- end
2419
-
2420
- context "when providing a string" do
2421
-
2422
- let(:selection) do
2423
- query.where(:field.with_size => "10")
2424
- end
2425
-
2426
- it "adds the $size criterion" do
2427
- expect(selection.selector).to eq(
2428
- { "field" => { "$size" => 10 }}
2429
- )
2430
- end
2431
-
2432
- it "returns a cloned query" do
2433
- expect(selection).to_not eq(query)
2434
- end
2435
- end
2436
- end
2437
-
2438
- context "when performing a $type" do
2439
-
2440
- let(:selection) do
2441
- query.where(:field.with_type => 10)
2442
- end
2443
-
2444
- it "adds the $type criterion" do
2445
- expect(selection.selector).to eq(
2446
- { "field" => { "$type" => 10 }}
2447
- )
2448
- end
2449
-
2450
- it "returns a cloned query" do
2451
- expect(selection).to_not eq(query)
2452
- end
2453
- end
2454
- end
2455
-
2456
- context 'when using an MQL logical operator manually' do
2457
- let(:base_query) do
2458
- query.where(test: 1)
2459
- end
2460
-
2461
- let(:selection) do
2462
- base_query.where(mql_operator => ['hello' => 'world'])
2463
- end
2464
-
2465
- shared_examples_for 'adds conditions to existing query' do
2466
- it 'adds conditions to existing query' do
2467
- selection.selector.should == {
2468
- 'test' => 1,
2469
- mql_operator => ['hello' => 'world'],
2470
- }
2471
- end
2472
- end
2473
-
2474
- shared_examples_for 'adds conditions to existing query with an extra $and' do
2475
- it 'adds conditions to existing query' do
2476
- selection.selector.should == {
2477
- 'test' => 1,
2478
- mql_operator => ['hello' => 'world'],
2479
- }
2480
- end
2481
- end
2482
-
2483
- context '$or' do
2484
- let(:mql_operator) { '$or' }
2485
-
2486
- it_behaves_like 'adds conditions to existing query with an extra $and'
2487
- end
2488
-
2489
- context '$nor' do
2490
- let(:mql_operator) { '$nor' }
2491
-
2492
- it_behaves_like 'adds conditions to existing query with an extra $and'
2493
- end
2494
-
2495
- context '$not' do
2496
- let(:mql_operator) { '$not' }
2497
-
2498
- it_behaves_like 'adds conditions to existing query'
2499
- end
2500
-
2501
- context '$and' do
2502
- let(:mql_operator) { '$and' }
2503
-
2504
- it_behaves_like 'adds conditions to existing query'
2505
- end
2506
- end
2507
- end
2508
-
2509
1945
  describe Symbol do
2510
1946
 
2511
1947
  describe "#all" do