mongoid 7.0.2 → 7.0.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/mongoid/association/referenced/eager.rb +4 -1
  4. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +3 -1
  5. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  6. data/lib/mongoid/association/relatable.rb +90 -10
  7. data/lib/mongoid/clients/options.rb +6 -4
  8. data/lib/mongoid/copyable.rb +2 -2
  9. data/lib/mongoid/criteria/options.rb +2 -2
  10. data/lib/mongoid/criteria/queryable/selectable.rb +33 -6
  11. data/lib/mongoid/document.rb +11 -4
  12. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  13. data/lib/mongoid/extensions/regexp.rb +1 -0
  14. data/lib/mongoid/matchable.rb +3 -1
  15. data/lib/mongoid/matchable/eq.rb +22 -0
  16. data/lib/mongoid/matchable/ne.rb +1 -1
  17. data/lib/mongoid/persistence_context.rb +20 -5
  18. data/lib/mongoid/query_cache.rb +8 -4
  19. data/lib/mongoid/railtie.rb +17 -0
  20. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  21. data/lib/mongoid/scopable.rb +3 -3
  22. data/lib/mongoid/threaded.rb +36 -0
  23. data/lib/mongoid/version.rb +1 -1
  24. data/spec/app/models/minim.rb +7 -0
  25. data/spec/app/models/store_as_dup_test3.rb +7 -0
  26. data/spec/app/models/store_as_dup_test4.rb +7 -0
  27. data/spec/config/mongoid.yml +12 -3
  28. data/spec/integration/associations/belongs_to_spec.rb +13 -0
  29. data/spec/lite_spec_helper.rb +56 -0
  30. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +24 -5
  31. data/spec/mongoid/association/referenced/belongs_to_spec.rb +46 -3
  32. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +21 -2
  33. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +56 -0
  34. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -0
  35. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +3 -3
  36. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  37. data/spec/mongoid/association/referenced/has_many_models.rb +37 -0
  38. data/spec/mongoid/association/referenced/has_many_spec.rb +3 -3
  39. data/spec/mongoid/association/referenced/has_one_models.rb +48 -0
  40. data/spec/mongoid/association/referenced/has_one_spec.rb +51 -4
  41. data/spec/mongoid/clients/factory_spec.rb +24 -18
  42. data/spec/mongoid/clients/options_spec.rb +40 -37
  43. data/spec/mongoid/clients_spec.rb +68 -8
  44. data/spec/mongoid/config_spec.rb +3 -1
  45. data/spec/mongoid/contextual/mongo_spec.rb +5 -2
  46. data/spec/mongoid/copyable_spec.rb +40 -6
  47. data/spec/mongoid/copyable_spec_models.rb +17 -0
  48. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
  49. data/spec/mongoid/criteria/queryable/selectable_spec.rb +42 -3
  50. data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
  51. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  52. data/spec/mongoid/criteria_spec.rb +18 -3
  53. data/spec/mongoid/document_spec.rb +81 -2
  54. data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
  55. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  56. data/spec/mongoid/fields_spec.rb +1 -1
  57. data/spec/mongoid/findable_spec.rb +1 -1
  58. data/spec/mongoid/matchable/eq_spec.rb +48 -0
  59. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  60. data/spec/mongoid/persistence_context_spec.rb +1 -1
  61. data/spec/mongoid/query_cache_spec.rb +59 -6
  62. data/spec/mongoid/scopable_spec.rb +13 -0
  63. data/spec/mongoid/threaded_spec.rb +68 -0
  64. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  65. data/spec/spec_helper.rb +35 -25
  66. data/spec/support/constraints.rb +101 -0
  67. data/spec/support/macros.rb +20 -0
  68. data/spec/support/spec_config.rb +39 -0
  69. metadata +471 -460
  70. checksums.yaml.gz.sig +0 -0
  71. data.tar.gz.sig +0 -2
  72. metadata.gz.sig +0 -0
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require_relative '../has_and_belongs_to_many_models'
2
3
 
3
4
  describe Mongoid::Association::Referenced::HasAndBelongsToMany::Eager do
4
5
 
@@ -41,7 +42,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Eager do
41
42
  Person.create!(houses: 3.times.map { House.create! })
42
43
  end
43
44
 
44
- context "when including the has_and_belongs_to_many relation" do
45
+ context "when including the has_and_belongs_to_many association" do
45
46
 
46
47
  it "queries twice" do
47
48
  expect_query(2) do
@@ -60,7 +61,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Eager do
60
61
  end
61
62
  end
62
63
 
63
- context "when the relation is not polymorphic" do
64
+ context "when the association is not polymorphic" do
64
65
 
65
66
  let(:eager) do
66
67
  Person.asc(:_id).includes(:preferences).last
@@ -129,5 +130,23 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Eager do
129
130
  end
130
131
  end
131
132
  end
133
+
134
+ context "when all the values for the has_and_belongs_to_many association are empty" do
135
+
136
+ before do
137
+ 2.times { |i| HabtmmPerson.create! }
138
+ end
139
+
140
+ it "only queries once for the parent documents" do
141
+ found_person = false
142
+ expect_query(1) do
143
+ HabtmmPerson.all.includes(:tickets).each do |person|
144
+ expect(person.tickets).to eq []
145
+ found_person = true
146
+ end
147
+ end
148
+ expect(found_person).to be true
149
+ end
150
+ end
132
151
  end
133
152
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require_relative '../has_and_belongs_to_many_models'
5
+
6
+ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
7
+ context 'with primary_key and foreign_key given' do
8
+ let(:company) { HabtmmCompany.create!(c_id: 123) }
9
+ let(:employee) { HabtmmEmployee.create!(e_id: 456) }
10
+
11
+ before do
12
+ company.employees << employee
13
+ end
14
+
15
+ it 'references correct field' do
16
+ expect(company.e_ids).to eq([456])
17
+ end
18
+
19
+ describe 'nullify' do
20
+ before do
21
+ company.employees << repl_employee
22
+ company.save!
23
+ expect(company.employees.length).to eq(2)
24
+ repl_employee.habtmm_company_ids = [company.id]
25
+ repl_employee.save!
26
+ repl_employee.reload
27
+ expect(repl_employee.habtmm_company_ids).to eq([company.id])
28
+ end
29
+
30
+ context 'without replacement' do
31
+ let(:repl_employee) { HabtmmEmployee.create!(e_id: 444) }
32
+
33
+ it 'disassociates child from parent' do
34
+ company.employees.nullify
35
+ repl_employee.reload
36
+ expect(repl_employee.habtmm_company_ids).to eq([])
37
+ end
38
+ end
39
+
40
+ context 'with replacement' do
41
+ let(:repl_employee) { HabtmmEmployee.create!(e_id: 444) }
42
+
43
+ before do
44
+ company.employees << repl_employee
45
+ expect(company.employees.length).to eq(2)
46
+ end
47
+
48
+ it 'keeps replacement associated with the parent' do
49
+ company.employees.nullify([repl_employee])
50
+ repl_employee.reload
51
+ expect(repl_employee.habtmm_company_ids).to eq([company.id])
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ class HabtmmCompany
2
+ include Mongoid::Document
3
+
4
+ field :c_id, type: Integer
5
+ field :e_ids, type: Array
6
+ has_and_belongs_to_many :employees, primary_key: :e_id, foreign_key: :e_ids, class_name: 'HabtmmEmployee'
7
+ end
8
+
9
+ class HabtmmEmployee
10
+ include Mongoid::Document
11
+
12
+ field :e_id, type: Integer
13
+ field :c_ids, type: Array
14
+ field :habtmm_company_ids, type: Array
15
+ has_and_belongs_to_many :companies, primary_key: :c_id, foreign_key: :c_ids, class_name: 'HabtmmCompany'
16
+ end
17
+
18
+ class HabtmmTicket
19
+ include Mongoid::Document
20
+ end
21
+
22
+ class HabtmmPerson
23
+ include Mongoid::Document
24
+
25
+ has_and_belongs_to_many :tickets, class_name: 'HabtmmTicket'
26
+ end
@@ -654,7 +654,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
654
654
  end
655
655
  end
656
656
 
657
- describe '#klass' do
657
+ describe '#relation_class' do
658
658
 
659
659
  context 'when the :class_name option is specified' do
660
660
 
@@ -668,14 +668,14 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
668
668
  end
669
669
 
670
670
  it 'returns the class name option' do
671
- expect(association.klass).to eq(_class)
671
+ expect(association.relation_class).to eq(_class)
672
672
  end
673
673
  end
674
674
 
675
675
  context 'when the class_name option is not specified' do
676
676
 
677
677
  it 'uses the name of the relation to deduce the class name' do
678
- expect(association.klass).to eq(HasManyRightObject)
678
+ expect(association.relation_class).to eq(HasManyRightObject)
679
679
  end
680
680
  end
681
681
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require_relative '../has_many_models'
5
+
6
+ describe Mongoid::Association::Referenced::HasMany::Proxy do
7
+ context 'with primary_key and foreign_key given' do
8
+ let(:company) { HmmCompany.create!(p: 123) }
9
+ let(:criteria) { company.emails }
10
+
11
+ it 'generates correct query' do
12
+ expect(criteria.selector).to eq('f' => 123)
13
+ end
14
+
15
+ context 'unscoped' do
16
+ let(:criteria) { company.emails.unscoped }
17
+
18
+ it 'generates correct query' do
19
+ expect(criteria.selector).to eq('f' => 123)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ class HmmCompany
2
+ include Mongoid::Document
3
+
4
+ field :p, type: Integer
5
+ has_many :emails, primary_key: :p, foreign_key: :f, class_name: 'HmmEmail'
6
+ end
7
+
8
+ class HmmEmail
9
+ include Mongoid::Document
10
+
11
+ field :f, type: Integer
12
+ belongs_to :company, primary_key: :p, foreign_key: :f, class_name: 'HmmCompany'
13
+ end
14
+
15
+ class HmmSchool
16
+ include Mongoid::Document
17
+
18
+ has_many :students, class_name: 'HmmStudent'
19
+
20
+ field :district, type: String
21
+ field :team, type: String
22
+ end
23
+
24
+ class HmmStudent
25
+ include Mongoid::Document
26
+
27
+ belongs_to :school, class_name: 'HmmSchool'
28
+
29
+ field :name, type: String
30
+ field :grade, type: Integer, default: 3
31
+ end
32
+
33
+ class HmmTicket
34
+ include Mongoid::Document
35
+
36
+ belongs_to :person
37
+ end
@@ -918,7 +918,7 @@ describe Mongoid::Association::Referenced::HasMany do
918
918
  end
919
919
  end
920
920
 
921
- describe '#klass' do
921
+ describe '#relation_class' do
922
922
 
923
923
  context 'when the :class_name option is specified' do
924
924
 
@@ -932,14 +932,14 @@ describe Mongoid::Association::Referenced::HasMany do
932
932
  end
933
933
 
934
934
  it 'returns the class name option' do
935
- expect(association.klass).to eq(_class)
935
+ expect(association.relation_class).to eq(_class)
936
936
  end
937
937
  end
938
938
 
939
939
  context 'when the class_name option is not specified' do
940
940
 
941
941
  it 'uses the name of the relation to deduce the class name' do
942
- expect(association.klass).to eq(BelongingObject)
942
+ expect(association.relation_class).to eq(BelongingObject)
943
943
  end
944
944
  end
945
945
  end
@@ -0,0 +1,48 @@
1
+ class HomCollege
2
+ include Mongoid::Document
3
+
4
+ has_one :accreditation, class_name: 'HomAccreditation'
5
+
6
+ field :state, type: String
7
+ end
8
+
9
+ class HomAccreditation
10
+ include Mongoid::Document
11
+
12
+ belongs_to :college, class_name: 'HomCollege'
13
+
14
+ field :degree, type: String
15
+ field :year, type: Integer, default: 2012
16
+ end
17
+
18
+ class HomAccreditation::Child
19
+ include Mongoid::Document
20
+
21
+ belongs_to :hom_college
22
+ end
23
+
24
+ module HomNs
25
+ class PrefixedParent
26
+ include Mongoid::Document
27
+
28
+ has_one :child, class_name: 'PrefixedChild'
29
+ end
30
+
31
+ class PrefixedChild
32
+ include Mongoid::Document
33
+
34
+ belongs_to :parent, class_name: 'PrefixedParent'
35
+ end
36
+ end
37
+
38
+ class HomPolymorphicParent
39
+ include Mongoid::Document
40
+
41
+ has_one :p_child, as: :parent
42
+ end
43
+
44
+ class HomPolymorphicChild
45
+ include Mongoid::Document
46
+
47
+ belongs_to :p_parent, polymorphic: true
48
+ end
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require_relative './has_one_models'
2
3
 
3
4
  describe Mongoid::Association::Referenced::HasOne do
4
5
 
@@ -926,6 +927,16 @@ describe Mongoid::Association::Referenced::HasOne do
926
927
  it 'returns the class name option' do
927
928
  expect(association.relation_class_name).to eq('OtherBelongingObject')
928
929
  end
930
+
931
+ context 'when the class is namespaced' do
932
+ let(:association) do
933
+ HomNs::PrefixedParent.relations['child']
934
+ end
935
+
936
+ it 'returns unqualified class name as given in the :class_name option' do
937
+ expect(association.relation_class_name).to eq('PrefixedChild')
938
+ end
939
+ end
929
940
  end
930
941
 
931
942
  context 'when the class_name option is not specified' do
@@ -936,7 +947,7 @@ describe Mongoid::Association::Referenced::HasOne do
936
947
  end
937
948
  end
938
949
 
939
- describe '#klass' do
950
+ describe '#relation_class' do
940
951
 
941
952
  context 'when the :class_name option is specified' do
942
953
 
@@ -950,22 +961,48 @@ describe Mongoid::Association::Referenced::HasOne do
950
961
  end
951
962
 
952
963
  it 'returns the class name option' do
953
- expect(association.klass).to eq(_class)
964
+ expect(association.relation_class).to eq(_class)
965
+ end
966
+
967
+ context 'when the class is namespaced' do
968
+ let(:association) do
969
+ HomNs::PrefixedParent.relations['child']
970
+ end
971
+
972
+ it 'returns resolved class instance' do
973
+ expect(association.relation_class).to eq(HomNs::PrefixedChild)
974
+ end
954
975
  end
955
976
  end
956
977
 
957
978
  context 'when the class_name option is not specified' do
958
979
 
959
980
  it 'uses the name of the relation to deduce the class name' do
960
- expect(association.klass).to eq(BelongingObject)
981
+ expect(association.relation_class).to eq(BelongingObject)
961
982
  end
962
983
  end
963
984
  end
964
985
 
986
+ describe '#klass' do
987
+ it 'is the target class' do
988
+ expect(association.klass).to eq(BelongingObject)
989
+ end
990
+ end
991
+
965
992
  describe '#inverse_class_name' do
966
993
 
967
994
  it 'returns the name of the owner class' do
968
- expect(association.inverse_class_name).to eq(OwnerObject.name)
995
+ expect(association.inverse_class_name).to eq('OwnerObject')
996
+ end
997
+
998
+ context 'polymorphic association' do
999
+ let(:association) do
1000
+ has_one_class.has_one :belonging_object, as: :bar
1001
+ end
1002
+
1003
+ it 'returns the name of the owner class' do
1004
+ expect(association.inverse_class_name).to eq(OwnerObject.name)
1005
+ end
969
1006
  end
970
1007
  end
971
1008
 
@@ -974,6 +1011,16 @@ describe Mongoid::Association::Referenced::HasOne do
974
1011
  it 'returns the owner class' do
975
1012
  expect(association.inverse_class).to be(OwnerObject)
976
1013
  end
1014
+
1015
+ context 'polymorphic association' do
1016
+ let(:association) do
1017
+ has_one_class.has_one :belonging_object, as: :bar
1018
+ end
1019
+
1020
+ it 'returns the owner class' do
1021
+ expect(association.inverse_class).to be(OwnerObject)
1022
+ end
1023
+ end
977
1024
  end
978
1025
 
979
1026
  describe '#inverse_of' do
@@ -12,8 +12,8 @@ describe Mongoid::Clients::Factory do
12
12
 
13
13
  let(:config) do
14
14
  {
15
- default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
16
- secondary: { hosts: [ "127.0.0.1:27017" ], database: database_id }
15
+ default: { hosts: SpecConfig.instance.addresses, database: database_id },
16
+ secondary: { hosts: SpecConfig.instance.addresses, database: database_id }
17
17
  }
18
18
  end
19
19
 
@@ -38,7 +38,7 @@ describe Mongoid::Clients::Factory do
38
38
  end
39
39
 
40
40
  it "sets the cluster's seeds" do
41
- expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
41
+ expect(cluster.addresses.first.to_s).to eq(SpecConfig.instance.addresses.first)
42
42
  end
43
43
 
44
44
  it "sets the platform to Mongoid's platform constant" do
@@ -80,11 +80,11 @@ describe Mongoid::Clients::Factory do
80
80
  end
81
81
 
82
82
  it "sets the cluster's seed ports to 27017" do
83
- expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
83
+ expect(%w(127.0.0.1:27017 localhost:27017)).to include(cluster.addresses.first.to_s)
84
84
  end
85
85
 
86
86
  it "sets ips with no ports to 27017" do
87
- expect(default.cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
87
+ expect(%w(127.0.0.1:27017 localhost:27017)).to include(cluster.addresses.first.to_s)
88
88
  end
89
89
  end
90
90
 
@@ -120,7 +120,7 @@ describe Mongoid::Clients::Factory do
120
120
  end
121
121
 
122
122
  it "sets the cluster's seeds" do
123
- expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
123
+ expect(%w(127.0.0.1:27017 localhost:27017)).to include(cluster.addresses.first.to_s)
124
124
  end
125
125
 
126
126
  it "sets the database" do
@@ -181,7 +181,7 @@ describe Mongoid::Clients::Factory do
181
181
  context "when no name is provided" do
182
182
 
183
183
  let(:config) do
184
- { default: { hosts: ["127.0.0.1:27017"], database: database_id }}
184
+ { default: { hosts: SpecConfig.instance.addresses, database: database_id }}
185
185
  end
186
186
 
187
187
  before do
@@ -200,7 +200,7 @@ describe Mongoid::Clients::Factory do
200
200
  client.cluster
201
201
  end
202
202
 
203
- let(:seeds) do
203
+ let(:cluster_addresses) do
204
204
  cluster.addresses.map{ |address| address.to_s }
205
205
  end
206
206
 
@@ -208,8 +208,10 @@ describe Mongoid::Clients::Factory do
208
208
  expect(client).to be_a(Mongo::Client)
209
209
  end
210
210
 
211
- it "sets the cluster's seeds" do
212
- expect(seeds).to eq([ "127.0.0.1:27017" ])
211
+ it "sets the cluster's addresses" do
212
+ SpecConfig.instance.addresses.each do |address|
213
+ expect(cluster_addresses).to include(address)
214
+ end
213
215
  end
214
216
  end
215
217
 
@@ -230,7 +232,7 @@ describe Mongoid::Clients::Factory do
230
232
  describe ".default" do
231
233
 
232
234
  let(:config) do
233
- { default: { hosts: ["127.0.0.1:27017"], database: database_id }}
235
+ { default: { hosts: SpecConfig.instance.addresses, database: database_id }}
234
236
  end
235
237
 
236
238
  before do
@@ -249,7 +251,7 @@ describe Mongoid::Clients::Factory do
249
251
  client.cluster
250
252
  end
251
253
 
252
- let(:seeds) do
254
+ let(:cluster_addresses) do
253
255
  cluster.addresses.map{ |address| address.to_s }
254
256
  end
255
257
 
@@ -257,8 +259,10 @@ describe Mongoid::Clients::Factory do
257
259
  expect(client).to be_a(Mongo::Client)
258
260
  end
259
261
 
260
- it "sets the cluster's seeds" do
261
- expect(seeds).to eq([ "127.0.0.1:27017" ])
262
+ it "sets the cluster's addresses" do
263
+ SpecConfig.instance.addresses.each do |address|
264
+ expect(cluster_addresses).to include(address)
265
+ end
262
266
  end
263
267
  end
264
268
 
@@ -267,7 +271,7 @@ describe Mongoid::Clients::Factory do
267
271
  let(:config) do
268
272
  {
269
273
  default: {
270
- hosts: [ "127.0.0.1:27017" ],
274
+ hosts: SpecConfig.instance.addresses,
271
275
  database: database_id,
272
276
  options: {
273
277
  "server_selection_timeout" => 10,
@@ -293,7 +297,7 @@ describe Mongoid::Clients::Factory do
293
297
  client.cluster
294
298
  end
295
299
 
296
- let(:seeds) do
300
+ let(:cluster_addresses) do
297
301
  cluster.addresses.map{ |address| address.to_s }
298
302
  end
299
303
 
@@ -301,8 +305,10 @@ describe Mongoid::Clients::Factory do
301
305
  expect(client).to be_a(Mongo::Client)
302
306
  end
303
307
 
304
- it "sets the cluster's seeds" do
305
- expect(seeds).to eq([ "127.0.0.1:27017" ])
308
+ it "sets the cluster's addresses" do
309
+ SpecConfig.instance.addresses.each do |address|
310
+ expect(cluster_addresses).to include(address)
311
+ end
306
312
  end
307
313
 
308
314
  it "sets the server selection timeout" do