mongoid 7.0.3 → 7.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +1 -0
  4. data/LICENSE +1 -0
  5. data/README.md +3 -2
  6. data/Rakefile +12 -0
  7. data/lib/mongoid.rb +2 -1
  8. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  9. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  10. data/lib/mongoid/association/proxy.rb +1 -1
  11. data/lib/mongoid/association/relatable.rb +23 -21
  12. data/lib/mongoid/atomic.rb +13 -3
  13. data/lib/mongoid/atomic/paths/embedded.rb +1 -1
  14. data/lib/mongoid/attributes.rb +28 -20
  15. data/lib/mongoid/attributes/dynamic.rb +15 -14
  16. data/lib/mongoid/config/environment.rb +21 -8
  17. data/lib/mongoid/copyable.rb +5 -1
  18. data/lib/mongoid/criteria.rb +7 -1
  19. data/lib/mongoid/criteria/modifiable.rb +13 -2
  20. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  21. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  22. data/lib/mongoid/criteria/queryable/key.rb +67 -8
  23. data/lib/mongoid/criteria/queryable/mergeable.rb +5 -4
  24. data/lib/mongoid/criteria/queryable/selectable.rb +3 -4
  25. data/lib/mongoid/criteria/queryable/selector.rb +9 -31
  26. data/lib/mongoid/extensions/hash.rb +4 -2
  27. data/lib/mongoid/extensions/regexp.rb +1 -1
  28. data/lib/mongoid/extensions/string.rb +5 -3
  29. data/lib/mongoid/fields.rb +2 -1
  30. data/lib/mongoid/matchable.rb +14 -15
  31. data/lib/mongoid/matchable/all.rb +4 -3
  32. data/lib/mongoid/matchable/default.rb +71 -24
  33. data/lib/mongoid/matchable/regexp.rb +2 -2
  34. data/lib/mongoid/persistable/pushable.rb +11 -2
  35. data/lib/mongoid/persistence_context.rb +6 -6
  36. data/lib/mongoid/positional.rb +1 -1
  37. data/lib/mongoid/query_cache.rb +3 -2
  38. data/lib/mongoid/validatable/macros.rb +1 -1
  39. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  40. data/lib/mongoid/version.rb +2 -1
  41. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  42. data/spec/README.md +18 -0
  43. data/spec/app/models/delegating_patient.rb +16 -0
  44. data/spec/app/models/other_owner_object.rb +2 -0
  45. data/spec/integration/app_spec.rb +192 -0
  46. data/spec/integration/associations/embedded_spec.rb +62 -0
  47. data/spec/integration/criteria/time_with_zone_spec.rb +32 -0
  48. data/spec/integration/document_spec.rb +22 -0
  49. data/spec/integration/matchable_spec.rb +680 -0
  50. data/spec/lite_spec_helper.rb +15 -5
  51. data/spec/mongoid/association/embedded/embedded_in_spec.rb +58 -0
  52. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  53. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  54. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +6 -0
  55. data/spec/mongoid/association/embedded/embeds_one_models.rb +51 -0
  56. data/spec/mongoid/association/embedded/embeds_one_spec.rb +46 -0
  57. data/spec/mongoid/association/referenced/belongs_to_spec.rb +23 -6
  58. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +2 -1
  59. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  60. data/spec/mongoid/association/referenced/has_one_spec.rb +12 -2
  61. data/spec/mongoid/attributes/dynamic_spec.rb +153 -0
  62. data/spec/mongoid/attributes_spec.rb +19 -7
  63. data/spec/mongoid/clients/factory_spec.rb +2 -2
  64. data/spec/mongoid/clients/options_spec.rb +4 -4
  65. data/spec/mongoid/clients/sessions_spec.rb +20 -7
  66. data/spec/mongoid/clients/transactions_spec.rb +36 -15
  67. data/spec/mongoid/clients_spec.rb +2 -2
  68. data/spec/mongoid/contextual/atomic_spec.rb +20 -10
  69. data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
  70. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  71. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  72. data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
  73. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
  74. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  75. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  76. data/spec/mongoid/criteria/queryable/key_spec.rb +48 -6
  77. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +762 -0
  78. data/spec/mongoid/criteria/queryable/selectable_spec.rb +5 -224
  79. data/spec/mongoid/criteria/queryable/selector_spec.rb +37 -0
  80. data/spec/mongoid/criteria_spec.rb +7 -2
  81. data/spec/mongoid/document_fields_spec.rb +88 -0
  82. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  83. data/spec/mongoid/extensions/string_spec.rb +35 -7
  84. data/spec/mongoid/indexable_spec.rb +6 -4
  85. data/spec/mongoid/matchable/default_spec.rb +10 -3
  86. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  87. data/spec/mongoid/matchable_spec.rb +2 -2
  88. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  89. data/spec/mongoid/query_cache_spec.rb +2 -1
  90. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  91. data/spec/mongoid/scopable_spec.rb +2 -1
  92. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  93. data/spec/mongoid/tasks/database_spec.rb +1 -1
  94. data/spec/mongoid/validatable/uniqueness_spec.rb +33 -6
  95. data/spec/spec_helper.rb +4 -37
  96. data/spec/support/child_process_helper.rb +76 -0
  97. data/spec/support/cluster_config.rb +158 -0
  98. data/spec/support/constraints.rb +29 -19
  99. data/spec/support/expectations.rb +17 -3
  100. data/spec/support/spec_config.rb +12 -4
  101. metadata +525 -464
  102. metadata.gz.sig +2 -0
@@ -277,49 +277,77 @@ describe Mongoid::Extensions::String do
277
277
  context "when the string is an integer" do
278
278
 
279
279
  it "returns true" do
280
- expect("1234").to be_numeric
280
+ expect("1234".numeric?).to eq(true)
281
281
  end
282
282
  end
283
283
 
284
284
  context "when string is a float" do
285
285
 
286
286
  it "returns true" do
287
- expect("1234.123").to be_numeric
287
+ expect("1234.123".numeric?).to eq(true)
288
288
  end
289
289
  end
290
290
 
291
291
  context "when the string is has exponents" do
292
292
 
293
293
  it "returns true" do
294
- expect("1234.123123E4").to be_numeric
294
+ expect("1234.123123E4".numeric?).to eq(true)
295
295
  end
296
296
  end
297
297
 
298
298
  context "when the string is non numeric" do
299
299
 
300
300
  it "returns false" do
301
- expect("blah").to_not be_numeric
301
+ expect("blah".numeric?).to eq(false)
302
302
  end
303
303
  end
304
304
 
305
305
  context "when the string is NaN" do
306
306
 
307
307
  it "returns true" do
308
- expect("NaN").to be_numeric
308
+ expect("NaN".numeric?).to eq(true)
309
+ end
310
+ end
311
+
312
+ context "when the string is NaN and junk in front" do
313
+
314
+ it "returns false" do
315
+ expect("a\nNaN".numeric?).to eq(false)
316
+ end
317
+ end
318
+
319
+ context "when the string is NaN and whitespace at end" do
320
+
321
+ it "returns false" do
322
+ expect("NaN\n".numeric?).to eq(false)
309
323
  end
310
324
  end
311
325
 
312
326
  context "when the string is Infinity" do
313
327
 
314
328
  it "returns true" do
315
- expect("Infinity").to be_numeric
329
+ expect("Infinity".numeric?).to eq(true)
330
+ end
331
+ end
332
+
333
+ context "when the string contains Infinity and junk in front" do
334
+
335
+ it "returns false" do
336
+ expect("a\nInfinity".numeric?).to eq(false)
337
+ end
338
+ end
339
+
340
+ context "when the string contains Infinity and whitespace at end" do
341
+
342
+ it "returns false" do
343
+ expect("Infinity\n".numeric?).to eq(false)
316
344
  end
317
345
  end
318
346
 
319
347
  context "when the string is -Infinity" do
320
348
 
321
349
  it "returns true" do
322
- expect("-Infinity").to be_numeric
350
+ expect("-Infinity".numeric?).to eq(true)
323
351
  end
324
352
  end
325
353
  end
@@ -45,7 +45,7 @@ describe Mongoid::Indexable do
45
45
  end
46
46
  end
47
47
 
48
- context "when database specific options exist", if: non_legacy_server? do
48
+ context "when database specific options exist" do
49
49
 
50
50
  let(:klass) do
51
51
  Class.new do
@@ -95,7 +95,7 @@ describe Mongoid::Indexable do
95
95
  end
96
96
  end
97
97
 
98
- context "when database options are specified", if: non_legacy_server? do
98
+ context "when database options are specified" do
99
99
 
100
100
  let(:klass) do
101
101
  Class.new do
@@ -133,7 +133,8 @@ describe Mongoid::Indexable do
133
133
  end
134
134
  end
135
135
 
136
- context "when a collation option is specified", if: collation_supported? do
136
+ context "when a collation option is specified" do
137
+ min_server_version '3.4'
137
138
 
138
139
  let(:klass) do
139
140
  Class.new do
@@ -308,7 +309,8 @@ describe Mongoid::Indexable do
308
309
  end
309
310
  end
310
311
 
311
- context "when providing a collation option", if: collation_supported? do
312
+ context "when providing a collation option" do
313
+ min_server_version '3.4'
312
314
 
313
315
  before do
314
316
  klass.index({ name: 1 }, collation: { locale: 'en_US', strength: 2 })
@@ -68,7 +68,7 @@ describe Mongoid::Matchable::Default do
68
68
  context "when the value is a regexp" do
69
69
 
70
70
  it "returns true" do
71
- expect(matcher._matches?(/^Test[3-5]$/)).to be true
71
+ expect(matcher._matches?(/\ATest[3-5]\z/)).to be true
72
72
  end
73
73
  end
74
74
  end
@@ -112,14 +112,21 @@ describe Mongoid::Matchable::Default do
112
112
  described_class.new(["Test1", "Test2", "Test3"])
113
113
  end
114
114
 
115
- context "when the attribute contains the value" do
115
+ context "when the attribute equals the value" do
116
116
 
117
117
  it "returns true" do
118
118
  expect(matcher._matches?(["Test1", "Test2", "Test3"])).to be true
119
119
  end
120
120
  end
121
121
 
122
- context "when the attribute does not contain the value" do
122
+ context "when the value contains same items as attribute but in different order" do
123
+
124
+ it "returns false" do
125
+ expect(matcher._matches?(["Test1", "Test3", "Test2"])).to be false
126
+ end
127
+ end
128
+
129
+ context "when the value is a subset of attribute" do
123
130
 
124
131
  it "returns false" do
125
132
  expect(matcher._matches?(["Test1", "Test2"])).to be false
@@ -15,7 +15,7 @@ describe Mongoid::Matchable::Regexp do
15
15
  context 'when a BSON::Regexp::Raw object is passed' do
16
16
 
17
17
  let(:regexp) do
18
- BSON::Regexp::Raw.new('^Em')
18
+ BSON::Regexp::Raw.new("\\AEm")
19
19
  end
20
20
 
21
21
  it 'compiles the regexp object to a native regexp for the matching' do
@@ -37,7 +37,7 @@ describe Mongoid::Matchable::Regexp do
37
37
  context 'when a native Regexp object is passed' do
38
38
 
39
39
  let(:regexp) do
40
- /^Em/
40
+ /\AEm/
41
41
  end
42
42
 
43
43
  it 'calls super with the native regexp' do
@@ -293,7 +293,7 @@ describe Mongoid::Matchable do
293
293
  context 'when a BSON::Regexp::Raw object is used' do
294
294
 
295
295
  let(:selector) do
296
- { street: BSON::Regexp::Raw.new("^Clarkenwell") }
296
+ { street: BSON::Regexp::Raw.new("\\AClarkenwell") }
297
297
  end
298
298
 
299
299
  it "returns true" do
@@ -304,7 +304,7 @@ describe Mongoid::Matchable do
304
304
  context 'when a native Regexp object is used' do
305
305
 
306
306
  let(:selector) do
307
- { street: /^Clarkenwell/ }
307
+ { street: /\AClarkenwell/ }
308
308
  end
309
309
 
310
310
  it "returns true" do
@@ -4,7 +4,7 @@ describe Mongoid::Persistable::Pushable do
4
4
 
5
5
  describe "#add_to_set" do
6
6
 
7
- context "when the document is a root document" do
7
+ context "when the document is a top level document" do
8
8
 
9
9
  shared_examples_for "a unique pushable root document" do
10
10
 
@@ -62,6 +62,60 @@ describe Mongoid::Persistable::Pushable do
62
62
 
63
63
  it_behaves_like "a unique pushable root document"
64
64
  end
65
+
66
+ context 'when the host model is not saved' do
67
+ context 'when attribute exists' do
68
+ let(:person) do
69
+ Person.new(aliases: [2])
70
+ end
71
+
72
+ it 'records the change' do
73
+ person.add_to_set({aliases: 1})
74
+
75
+ expect(person.aliases).to eq([2, 1])
76
+ end
77
+ end
78
+
79
+ context 'when attribute does not exist' do
80
+ let(:person) do
81
+ Person.new
82
+ end
83
+
84
+ it 'records the change' do
85
+ person.add_to_set({aliases: 1})
86
+
87
+ expect(person.aliases).to eq([1])
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'when the host model is loaded from database' do
93
+ context 'when attribute exists' do
94
+ let(:person) do
95
+ Person.create!(aliases: [2])
96
+ person = Person.last
97
+ end
98
+
99
+ it 'records the change' do
100
+ person.add_to_set({aliases: 1})
101
+
102
+ expect(person.aliases).to eq([2, 1])
103
+ end
104
+ end
105
+
106
+ context 'when attribute does not exist' do
107
+ let(:person) do
108
+ Person.create!
109
+ person = Person.last
110
+ end
111
+
112
+ it 'records the change' do
113
+ person.add_to_set({aliases: 1})
114
+
115
+ expect(person.aliases).to eq([1])
116
+ end
117
+ end
118
+ end
65
119
  end
66
120
 
67
121
  context "when the document is embedded" do
@@ -180,7 +180,8 @@ describe Mongoid::QueryCache do
180
180
  end
181
181
  end
182
182
 
183
- context 'when the first query has a collation', if: collation_supported? do
183
+ context 'when the first query has a collation' do
184
+ min_server_version '3.4'
184
185
 
185
186
  before do
186
187
  Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # describe Mongoid::Relations::Proxy do
4
4
  #
5
- # describe '#with', if: non_legacy_server? do
5
+ # describe '#with' do
6
6
  #
7
7
  # let(:circus) do
8
8
  # Circus.new
@@ -227,7 +227,8 @@ describe Mongoid::Scopable do
227
227
 
228
228
  context "when provided a criteria" do
229
229
 
230
- context 'when a collation is defined on the criteria', if: collation_supported? do
230
+ context 'when a collation is defined on the criteria' do
231
+ min_server_version '3.4'
231
232
 
232
233
  before do
233
234
  Band.scope(:tests, ->{ Band.where(name: 'TESTING').collation(locale: 'en_US', strength: 2) })
@@ -45,7 +45,7 @@ shared_context "rails rake task" do
45
45
  end
46
46
  end
47
47
 
48
- describe "db:drop", if: non_legacy_server? do
48
+ describe "db:drop" do
49
49
  include_context "rake task"
50
50
  include_context "rails rake task"
51
51
 
@@ -58,7 +58,7 @@ describe "db:drop", if: non_legacy_server? do
58
58
  end
59
59
  end
60
60
 
61
- describe "db:purge", if: non_legacy_server? do
61
+ describe "db:purge" do
62
62
  include_context "rake task"
63
63
  include_context "rails rake task"
64
64
 
@@ -71,7 +71,7 @@ describe "db:purge", if: non_legacy_server? do
71
71
  end
72
72
  end
73
73
 
74
- describe "db:seed", if: non_legacy_server? do
74
+ describe "db:seed" do
75
75
  include_context "rake task"
76
76
  include_context "rails rake task"
77
77
 
@@ -85,7 +85,7 @@ describe "db:seed", if: non_legacy_server? do
85
85
  end
86
86
  end
87
87
 
88
- describe "db:setup", if: non_legacy_server? do
88
+ describe "db:setup" do
89
89
  include_context "rake task"
90
90
  include_context "rails rake task"
91
91
 
@@ -117,7 +117,7 @@ describe "db:setup", if: non_legacy_server? do
117
117
  end
118
118
  end
119
119
 
120
- describe "db:reset", if: non_legacy_server? do
120
+ describe "db:reset" do
121
121
  include_context "rake task"
122
122
  include_context "rails rake task"
123
123
 
@@ -135,7 +135,7 @@ describe "db:reset", if: non_legacy_server? do
135
135
  end
136
136
  end
137
137
 
138
- describe "db:create", if: non_legacy_server? do
138
+ describe "db:create" do
139
139
  include_context "rake task"
140
140
  include_context "rails rake task"
141
141
 
@@ -144,7 +144,7 @@ describe "db:create", if: non_legacy_server? do
144
144
  end
145
145
  end
146
146
 
147
- describe "db:migrate", if: non_legacy_server? do
147
+ describe "db:migrate" do
148
148
  include_context "rake task"
149
149
  include_context "rails rake task"
150
150
 
@@ -153,7 +153,7 @@ describe "db:migrate", if: non_legacy_server? do
153
153
  end
154
154
  end
155
155
 
156
- describe "db:test:prepare", if: non_legacy_server? do
156
+ describe "db:test:prepare" do
157
157
  include_context "rake task"
158
158
  include_context "rails rake task"
159
159
 
@@ -174,7 +174,7 @@ describe "db:test:prepare", if: non_legacy_server? do
174
174
  end
175
175
  end
176
176
 
177
- describe "db:mongoid:create_indexes", if: non_legacy_server? do
177
+ describe "db:mongoid:create_indexes" do
178
178
  include_context "rake task"
179
179
 
180
180
  it_behaves_like "create_indexes"
@@ -198,7 +198,7 @@ describe "db:mongoid:create_indexes", if: non_legacy_server? do
198
198
  end
199
199
  end
200
200
 
201
- describe "db:mongoid:remove_undefined_indexes", if: non_legacy_server? do
201
+ describe "db:mongoid:remove_undefined_indexes" do
202
202
  include_context "rake task"
203
203
 
204
204
  it "receives remove_undefined_indexes" do
@@ -224,7 +224,7 @@ describe "db:mongoid:remove_undefined_indexes", if: non_legacy_server? do
224
224
  end
225
225
  end
226
226
 
227
- describe "db:mongoid:remove_indexes", if: non_legacy_server? do
227
+ describe "db:mongoid:remove_indexes" do
228
228
  include_context "rake task"
229
229
 
230
230
  it "receives remove_indexes" do
@@ -250,7 +250,7 @@ describe "db:mongoid:remove_indexes", if: non_legacy_server? do
250
250
  end
251
251
  end
252
252
 
253
- describe "db:mongoid:drop", if: non_legacy_server? do
253
+ describe "db:mongoid:drop" do
254
254
  include_context "rake task"
255
255
 
256
256
  it "works" do
@@ -266,7 +266,7 @@ describe "db:mongoid:drop", if: non_legacy_server? do
266
266
  end
267
267
  end
268
268
 
269
- describe "db:mongoid:purge", if: non_legacy_server? do
269
+ describe "db:mongoid:purge" do
270
270
  include_context "rake task"
271
271
 
272
272
  it "receives a purge" do
@@ -133,7 +133,7 @@ describe "Mongoid::Tasks::Database" do
133
133
  expect(removed_indexes).to be_empty
134
134
  end
135
135
 
136
- context 'when the index is a text index', if: non_legacy_server? do
136
+ context 'when the index is a text index' do
137
137
 
138
138
  before do
139
139
  class Band
@@ -796,20 +796,47 @@ describe Mongoid::Validatable::UniquenessValidator do
796
796
  end
797
797
  end
798
798
 
799
- context "when a range scope is provided" do
799
+ context "when a range condition is provided" do
800
800
 
801
801
  before do
802
- Dictionary.validates_uniqueness_of(:name, :scope => Dictionary.where(:year.gte => 1900, :year.lt => 2000))
803
- Dictionary.create(name: "French-English", year: 1950)
804
- Dictionary.create(name: "French-English", year: 1960)
802
+ Dictionary.validates_uniqueness_of(:name,
803
+ conditions: -> { Dictionary.where(:year.gte => 1900, :year.lt => 2000) })
805
804
  end
806
805
 
807
806
  after do
808
807
  Dictionary.reset_callbacks(:validate)
809
808
  end
810
809
 
811
- it "successfully prevents uniqueness violation" do
812
- expect(Dictionary.all.size).to eq(1)
810
+ context 'when multiple documents would match the condition' do
811
+ it "prevents creation of new document" do
812
+ Dictionary.create!(name: "French-English", year: 1950)
813
+
814
+ expect do
815
+ Dictionary.create!(name: "French-English", year: 1960)
816
+ end.to raise_error(Mongoid::Errors::Validations, /Name is already taken/)
817
+
818
+ expect(Dictionary.all.size).to eq(1)
819
+ end
820
+ end
821
+
822
+ context 'when only new document would match the condition' do
823
+ it 'creates the new document' do
824
+ Dictionary.create!(name: "French-English", year: 950)
825
+ expect do
826
+ Dictionary.create!(name: "French-English", year: 1950)
827
+ end.not_to raise_error
828
+ end
829
+ end
830
+
831
+ context 'when only existing document matches the condition' do
832
+ it 'creates the new document' do
833
+ pending 'https://jira.mongodb.org/browse/MONGOID-4815'
834
+
835
+ Dictionary.create!(name: "French-English", year: 1950)
836
+ expect do
837
+ Dictionary.create!(name: "French-English", year: 950)
838
+ end.not_to raise_error
839
+ end
813
840
  end
814
841
  end
815
842