mongoid 4.0.2 → 5.0.0

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/README.md +11 -19
  4. data/lib/config/locales/en.yml +33 -30
  5. data/lib/mongoid/atomic.rb +2 -4
  6. data/lib/mongoid/attributes/processing.rb +4 -1
  7. data/lib/mongoid/attributes/readonly.rb +2 -2
  8. data/lib/mongoid/attributes.rb +7 -7
  9. data/lib/mongoid/changeable.rb +4 -6
  10. data/lib/mongoid/clients/factory.rb +78 -0
  11. data/lib/mongoid/{sessions → clients}/options.rb +30 -19
  12. data/lib/mongoid/{sessions → clients}/storage_options.rb +27 -13
  13. data/lib/mongoid/{sessions → clients}/thread_options.rb +6 -3
  14. data/lib/mongoid/{sessions → clients}/validators/storage.rb +5 -2
  15. data/lib/mongoid/clients/validators.rb +2 -0
  16. data/lib/mongoid/clients.rb +141 -0
  17. data/lib/mongoid/composable.rb +3 -3
  18. data/lib/mongoid/config/environment.rb +1 -1
  19. data/lib/mongoid/config/options.rb +1 -1
  20. data/lib/mongoid/config/validators/{session.rb → client.rb} +31 -28
  21. data/lib/mongoid/config/validators/option.rb +1 -1
  22. data/lib/mongoid/config/validators.rb +1 -1
  23. data/lib/mongoid/config.rb +39 -41
  24. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  25. data/lib/mongoid/contextual/atomic.rb +11 -11
  26. data/lib/mongoid/contextual/command.rb +9 -6
  27. data/lib/mongoid/contextual/geo_near.rb +17 -1
  28. data/lib/mongoid/contextual/map_reduce.rb +12 -11
  29. data/lib/mongoid/contextual/memory.rb +2 -5
  30. data/lib/mongoid/contextual/mongo.rb +92 -82
  31. data/lib/mongoid/contextual/none.rb +13 -0
  32. data/lib/mongoid/copyable.rb +6 -1
  33. data/lib/mongoid/criteria.rb +37 -4
  34. data/lib/mongoid/document.rb +3 -4
  35. data/lib/mongoid/errors/{mixed_session_configuration.rb → mixed_client_configuration.rb} +5 -5
  36. data/lib/mongoid/errors/mongoid_error.rb +15 -9
  37. data/lib/mongoid/errors/no_client_config.rb +22 -0
  38. data/lib/mongoid/errors/{no_session_database.rb → no_client_database.rb} +4 -4
  39. data/lib/mongoid/errors/{no_session_hosts.rb → no_client_hosts.rb} +4 -4
  40. data/lib/mongoid/errors/{no_sessions_config.rb → no_clients_config.rb} +4 -4
  41. data/lib/mongoid/errors/no_default_client.rb +23 -0
  42. data/lib/mongoid/errors.rb +6 -6
  43. data/lib/mongoid/extensions/hash.rb +5 -1
  44. data/lib/mongoid/extensions/object.rb +3 -2
  45. data/lib/mongoid/extensions/set.rb +5 -5
  46. data/lib/mongoid/factory.rb +4 -2
  47. data/lib/mongoid/fields.rb +7 -2
  48. data/lib/mongoid/findable.rb +4 -1
  49. data/lib/mongoid/indexable.rb +15 -9
  50. data/lib/mongoid/persistable/creatable.rb +2 -2
  51. data/lib/mongoid/persistable/deletable.rb +3 -3
  52. data/lib/mongoid/persistable/incrementable.rb +1 -1
  53. data/lib/mongoid/persistable/logical.rb +1 -1
  54. data/lib/mongoid/persistable/poppable.rb +1 -1
  55. data/lib/mongoid/persistable/pullable.rb +2 -2
  56. data/lib/mongoid/persistable/pushable.rb +2 -2
  57. data/lib/mongoid/persistable/renamable.rb +1 -1
  58. data/lib/mongoid/persistable/settable.rb +1 -1
  59. data/lib/mongoid/persistable/unsettable.rb +1 -1
  60. data/lib/mongoid/persistable/updatable.rb +2 -2
  61. data/lib/mongoid/persistable/upsertable.rb +1 -1
  62. data/lib/mongoid/persistable.rb +1 -2
  63. data/lib/mongoid/query_cache.rb +98 -104
  64. data/lib/mongoid/railtie.rb +4 -25
  65. data/lib/mongoid/railties/database.rake +1 -1
  66. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -2
  67. data/lib/mongoid/relations/builders.rb +3 -1
  68. data/lib/mongoid/relations/counter_cache.rb +1 -1
  69. data/lib/mongoid/relations/embedded/batchable.rb +3 -10
  70. data/lib/mongoid/relations/embedded/many.rb +4 -2
  71. data/lib/mongoid/relations/embedded/one.rb +1 -0
  72. data/lib/mongoid/relations/many.rb +1 -0
  73. data/lib/mongoid/relations/metadata.rb +14 -0
  74. data/lib/mongoid/relations/proxy.rb +6 -6
  75. data/lib/mongoid/relations/referenced/many.rb +2 -1
  76. data/lib/mongoid/relations/targets/enumerable.rb +11 -11
  77. data/lib/mongoid/relations/touchable.rb +1 -1
  78. data/lib/mongoid/reloadable.rb +2 -2
  79. data/lib/mongoid/scopable.rb +6 -17
  80. data/lib/mongoid/selectable.rb +1 -36
  81. data/lib/mongoid/serializable.rb +2 -2
  82. data/lib/mongoid/stateful.rb +0 -1
  83. data/lib/mongoid/tasks/database.rake +2 -2
  84. data/lib/mongoid/tasks/database.rb +24 -17
  85. data/lib/mongoid/threaded/lifecycle.rb +21 -16
  86. data/lib/mongoid/threaded.rb +54 -33
  87. data/lib/mongoid/traversable.rb +17 -1
  88. data/lib/mongoid/validatable/queryable.rb +1 -1
  89. data/lib/mongoid/validatable/uniqueness.rb +3 -20
  90. data/lib/mongoid/validatable.rb +1 -1
  91. data/lib/mongoid/version.rb +1 -1
  92. data/lib/mongoid.rb +28 -21
  93. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +91 -57
  94. data/lib/rails/mongoid.rb +2 -2
  95. data/spec/app/models/audio.rb +1 -1
  96. data/spec/app/models/band.rb +1 -0
  97. data/spec/app/models/code.rb +6 -0
  98. data/spec/app/models/company.rb +5 -0
  99. data/spec/app/models/label.rb +7 -0
  100. data/spec/app/models/pub.rb +6 -0
  101. data/spec/app/models/staff.rb +7 -0
  102. data/spec/app/models/store_as_dup_test1.rb +5 -0
  103. data/spec/app/models/store_as_dup_test2.rb +5 -0
  104. data/spec/config/mongoid.yml +7 -25
  105. data/spec/mongoid/atomic/paths_spec.rb +3 -11
  106. data/spec/mongoid/attributes/nested_spec.rb +16 -16
  107. data/spec/mongoid/attributes/readonly_spec.rb +80 -18
  108. data/spec/mongoid/attributes_spec.rb +3 -3
  109. data/spec/mongoid/changeable_spec.rb +156 -0
  110. data/spec/mongoid/clients/factory_spec.rb +284 -0
  111. data/spec/mongoid/{sessions → clients}/options_spec.rb +4 -6
  112. data/spec/mongoid/clients_spec.rb +754 -0
  113. data/spec/mongoid/config/environment_spec.rb +14 -11
  114. data/spec/mongoid/config_spec.rb +33 -48
  115. data/spec/mongoid/contextual/atomic_spec.rb +1 -17
  116. data/spec/mongoid/contextual/geo_near_spec.rb +35 -0
  117. data/spec/mongoid/contextual/mongo_spec.rb +26 -83
  118. data/spec/mongoid/contextual/none_spec.rb +15 -0
  119. data/spec/mongoid/copyable_spec.rb +35 -1
  120. data/spec/mongoid/criteria/findable_spec.rb +197 -0
  121. data/spec/mongoid/criteria/modifiable_spec.rb +7 -29
  122. data/spec/mongoid/criteria_spec.rb +74 -91
  123. data/spec/mongoid/document_spec.rb +1 -1
  124. data/spec/mongoid/errors/{mixed_session_configuration_spec.rb → mixed_client_configuration_spec.rb} +1 -1
  125. data/spec/mongoid/errors/mongoid_error_spec.rb +19 -3
  126. data/spec/mongoid/errors/{no_session_config_spec.rb → no_client_config_spec.rb} +4 -4
  127. data/spec/mongoid/errors/{no_session_database_spec.rb → no_client_database_spec.rb} +4 -4
  128. data/spec/mongoid/errors/{no_session_hosts_spec.rb → no_client_hosts_spec.rb} +3 -3
  129. data/spec/mongoid/errors/{no_sessions_config_spec.rb → no_clients_config_spec.rb} +2 -2
  130. data/spec/mongoid/fields/localized_spec.rb +1 -0
  131. data/spec/mongoid/fields_spec.rb +1 -0
  132. data/spec/mongoid/findable_spec.rb +2 -23
  133. data/spec/mongoid/indexable_spec.rb +12 -8
  134. data/spec/mongoid/interceptable_spec.rb +15 -0
  135. data/spec/mongoid/persistable/settable_spec.rb +16 -0
  136. data/spec/mongoid/persistable/updatable_spec.rb +3 -2
  137. data/spec/mongoid/persistable_spec.rb +4 -4
  138. data/spec/mongoid/query_cache_spec.rb +13 -8
  139. data/spec/mongoid/relations/auto_save_spec.rb +1 -1
  140. data/spec/mongoid/relations/counter_cache_spec.rb +34 -0
  141. data/spec/mongoid/relations/eager/belongs_to_spec.rb +9 -0
  142. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +3 -3
  143. data/spec/mongoid/relations/embedded/many_spec.rb +123 -1
  144. data/spec/mongoid/relations/embedded/one_spec.rb +3 -3
  145. data/spec/mongoid/relations/proxy_spec.rb +28 -0
  146. data/spec/mongoid/relations/referenced/in_spec.rb +1 -1
  147. data/spec/mongoid/relations/referenced/many_spec.rb +47 -23
  148. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +1 -1
  149. data/spec/mongoid/relations/referenced/one_spec.rb +1 -1
  150. data/spec/mongoid/relations/targets/enumerable_spec.rb +9 -2
  151. data/spec/mongoid/reloadable_spec.rb +6 -6
  152. data/spec/mongoid/scopable_spec.rb +41 -28
  153. data/spec/mongoid/selectable_spec.rb +6 -16
  154. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  155. data/spec/mongoid/tasks/database_spec.rb +2 -2
  156. data/spec/mongoid/threaded_spec.rb +0 -7
  157. data/spec/mongoid/traversable_spec.rb +2 -2
  158. data/spec/mongoid/validatable/uniqueness_spec.rb +30 -1
  159. data/spec/mongoid_spec.rb +13 -15
  160. data/spec/rails/mongoid_spec.rb +13 -4
  161. data/spec/spec_helper.rb +44 -27
  162. data/spec/support/authorization.rb +12 -0
  163. data/spec/support/expectations.rb +14 -0
  164. metadata +50 -57
  165. data/lib/mongoid/contextual/find_and_modify.rb +0 -69
  166. data/lib/mongoid/contextual/text_search.rb +0 -178
  167. data/lib/mongoid/criteria/#findable.rb# +0 -141
  168. data/lib/mongoid/errors/no_default_session.rb +0 -23
  169. data/lib/mongoid/errors/no_session_config.rb +0 -22
  170. data/lib/mongoid/log_subscriber.rb +0 -55
  171. data/lib/mongoid/positional.rb +0 -71
  172. data/lib/mongoid/sessions/factory.rb +0 -131
  173. data/lib/mongoid/sessions/mongo_uri.rb +0 -93
  174. data/lib/mongoid/sessions/validators.rb +0 -2
  175. data/lib/mongoid/sessions.rb +0 -125
  176. data/lib/mongoid/support/query_counter.rb +0 -23
  177. data/spec/helpers.rb +0 -18
  178. data/spec/mongoid/#atomic_spec.rb# +0 -365
  179. data/spec/mongoid/contextual/find_and_modify_spec.rb +0 -220
  180. data/spec/mongoid/contextual/text_search_spec.rb +0 -209
  181. data/spec/mongoid/log_subscriber_spec.rb +0 -75
  182. data/spec/mongoid/positional_spec.rb +0 -222
  183. data/spec/mongoid/sessions/factory_spec.rb +0 -333
  184. data/spec/mongoid/sessions/mongo_uri_spec.rb +0 -103
  185. data/spec/mongoid/sessions_spec.rb +0 -1252
@@ -19,6 +19,17 @@ describe Mongoid::Attributes::Readonly do
19
19
  end
20
20
  end
21
21
 
22
+ context "when providing a field alias" do
23
+
24
+ before do
25
+ Person.attr_readonly :aliased_timestamp
26
+ end
27
+
28
+ it "adds the database field name to readonly attributes" do
29
+ expect(Person.readonly_attributes.to_a).to eq([ "at" ])
30
+ end
31
+ end
32
+
22
33
  context "when providing multiple fields" do
23
34
 
24
35
  before do
@@ -33,54 +44,71 @@ describe Mongoid::Attributes::Readonly do
33
44
  context "when creating a new document with a readonly field" do
34
45
 
35
46
  before do
36
- Person.attr_readonly :title, :terms
47
+ Person.attr_readonly :title, :terms, :aliased_timestamp
37
48
  end
38
49
 
39
50
  let(:person) do
40
- Person.create(title: "sir", terms: true)
51
+ Person.create(title: "sir", terms: true, aliased_timestamp: Time.at(42))
41
52
  end
42
53
 
43
54
  it "sets the first readonly value" do
44
55
  expect(person.title).to eq("sir")
45
56
  end
46
57
 
47
- it "sets subsequent readonly values" do
58
+ it "sets the second readonly value" do
48
59
  expect(person.terms).to be true
49
60
  end
50
61
 
62
+ it "sets the third readonly value" do
63
+ expect(person.aliased_timestamp).to eq(Time.at(42))
64
+ end
65
+
51
66
  it "persists the first readonly value" do
52
67
  expect(person.reload.title).to eq("sir")
53
68
  end
54
69
 
55
- it "persists subsequent readonly values" do
70
+ it "persists the second readonly value" do
56
71
  expect(person.reload.terms).to be true
57
72
  end
73
+
74
+ it "persists the third readonly value" do
75
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
76
+ end
58
77
  end
59
78
 
60
79
  context "when updating an existing readonly field" do
61
80
 
62
81
  before do
63
- Person.attr_readonly :title, :terms, :score
82
+ Person.attr_readonly :title, :terms, :score, :aliased_timestamp
64
83
  end
65
84
 
66
85
  let(:person) do
67
- Person.create(title: "sir", terms: true, score: 1)
86
+ Person.create(title: "sir", terms: true, score: 1, aliased_timestamp: Time.at(42))
68
87
  end
69
88
 
70
89
  context "when updating via the setter" do
71
90
 
72
91
  before do
73
92
  person.title = "mr"
93
+ person.aliased_timestamp = Time.at(43)
74
94
  person.save
75
95
  end
76
96
 
77
- it "does not update the field" do
97
+ it "does not update the first field" do
78
98
  expect(person.title).to eq("sir")
79
99
  end
80
100
 
81
- it "does not persist the changes" do
101
+ it "does not update the second field" do
102
+ expect(person.aliased_timestamp).to eq(Time.at(42))
103
+ end
104
+
105
+ it "does not persist the first field" do
82
106
  expect(person.reload.title).to eq("sir")
83
107
  end
108
+
109
+ it "does not persist the second field" do
110
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
111
+ end
84
112
  end
85
113
 
86
114
  context "when updating via inc" do
@@ -127,64 +155,98 @@ describe Mongoid::Attributes::Readonly do
127
155
 
128
156
  before do
129
157
  person[:title] = "mr"
158
+ person[:aliased_timestamp] = Time.at(43)
130
159
  person.save
131
160
  end
132
161
 
133
- it "does not update the field" do
162
+ it "does not update the first field" do
134
163
  expect(person.title).to eq("sir")
135
164
  end
136
165
 
137
- it "does not persist the changes" do
166
+ it "does not update the second field" do
167
+ expect(person.aliased_timestamp).to eq(Time.at(42))
168
+ end
169
+
170
+ it "does not persist the first field" do
138
171
  expect(person.reload.title).to eq("sir")
139
172
  end
173
+
174
+ it "does not persist the second field" do
175
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
176
+ end
140
177
  end
141
178
 
142
179
  context "when updating via write_attribute" do
143
180
 
144
181
  before do
145
182
  person.write_attribute(:title, "mr")
183
+ person.write_attribute(:aliased_timestamp, Time.at(43))
146
184
  person.save
147
185
  end
148
186
 
149
- it "does not update the field" do
187
+ it "does not update the first field" do
150
188
  expect(person.title).to eq("sir")
151
189
  end
152
190
 
153
- it "does not persist the changes" do
191
+ it "does not update the second field" do
192
+ expect(person.aliased_timestamp).to eq(Time.at(42))
193
+ end
194
+
195
+ it "does not persist the first field" do
154
196
  expect(person.reload.title).to eq("sir")
155
197
  end
198
+
199
+ it "does not persist the second field" do
200
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
201
+ end
156
202
  end
157
203
 
158
204
  context "when updating via update_attributes" do
159
205
 
160
206
  before do
161
- person.update_attributes(title: "mr")
207
+ person.update_attributes(title: "mr", aliased_timestamp: Time.at(43))
162
208
  person.save
163
209
  end
164
210
 
165
- it "does not update the field" do
211
+ it "does not update the first field" do
166
212
  expect(person.title).to eq("sir")
167
213
  end
168
214
 
169
- it "does not persist the changes" do
215
+ it "does not update the second field" do
216
+ expect(person.aliased_timestamp).to eq(Time.at(42))
217
+ end
218
+
219
+ it "does not persist the first field" do
170
220
  expect(person.reload.title).to eq("sir")
171
221
  end
222
+
223
+ it "does not persist the second field" do
224
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
225
+ end
172
226
  end
173
227
 
174
228
  context "when updating via update_attributes!" do
175
229
 
176
230
  before do
177
- person.update_attributes!(title: "mr")
231
+ person.update_attributes!(title: "mr", aliased_timestamp: Time.at(43))
178
232
  person.save
179
233
  end
180
234
 
181
- it "does not update the field" do
235
+ it "does not update the first field" do
182
236
  expect(person.title).to eq("sir")
183
237
  end
184
238
 
185
- it "does not persist the changes" do
239
+ it "does not update the second field" do
240
+ expect(person.aliased_timestamp).to eq(Time.at(42))
241
+ end
242
+
243
+ it "does not persist the first field" do
186
244
  expect(person.reload.title).to eq("sir")
187
245
  end
246
+
247
+ it "does not persist the second field" do
248
+ expect(person.reload.aliased_timestamp).to eq(Time.at(42))
249
+ end
188
250
  end
189
251
 
190
252
  context "when updating via update_attribute" do
@@ -172,7 +172,7 @@ describe Mongoid::Attributes do
172
172
  before do
173
173
  person.collection
174
174
  .find({ _id: person.id })
175
- .update({ "$unset" => { age: 1 }})
175
+ .update_one({ "$unset" => { age: 1 }})
176
176
  end
177
177
 
178
178
  context "when found" do
@@ -742,7 +742,7 @@ describe Mongoid::Attributes do
742
742
  before do
743
743
  person.collection
744
744
  .find({ _id: person.id })
745
- .update({ "$unset" => { age: 1 }})
745
+ .update_one({ "$unset" => { age: 1 }})
746
746
  Mongoid.raise_not_found_error = false
747
747
  person.reload
748
748
  Mongoid.raise_not_found_error = true
@@ -829,7 +829,7 @@ describe Mongoid::Attributes do
829
829
  before do
830
830
  person.collection
831
831
  .find({ _id: person.id })
832
- .update({ "$unset" => { age: 1 }})
832
+ .update_one({ "$unset" => { age: 1 }})
833
833
  Mongoid.raise_not_found_error = false
834
834
  person.reload
835
835
  Mongoid.raise_not_found_error = true
@@ -661,6 +661,24 @@ describe Mongoid::Changeable do
661
661
  it "returns an array of changed field names" do
662
662
  expect(person.changed).to include("title")
663
663
  end
664
+
665
+ end
666
+
667
+ context "When the document has changed but changed back to the original" do
668
+
669
+ let(:person) do
670
+ Person.instantiate(title: "Grand Poobah")
671
+ end
672
+
673
+ before do
674
+ person.title = "Captain Obvious"
675
+ person.title = nil
676
+ end
677
+
678
+ it "returns an array of changed field names" do
679
+ expect(person.changed).not_to include("title")
680
+ end
681
+
664
682
  end
665
683
 
666
684
  context "when the document has not changed" do
@@ -793,6 +811,58 @@ describe Mongoid::Changeable do
793
811
  end
794
812
  end
795
813
 
814
+ context "when changed? has been called before child elements size change" do
815
+
816
+ let(:person) do
817
+ Person.create
818
+ end
819
+
820
+ let(:address) do
821
+ person.addresses.create(street: "hobrecht")
822
+ end
823
+
824
+ let!(:location) do
825
+ address.locations.create(name: "home")
826
+ end
827
+
828
+ before do
829
+ person.changed?
830
+ end
831
+
832
+ context "when adding via new" do
833
+
834
+ before do
835
+ address.locations.new
836
+ end
837
+
838
+ it "returns true" do
839
+ expect(person).to be_changed
840
+ end
841
+ end
842
+
843
+ context "when adding via build" do
844
+
845
+ before do
846
+ address.locations.build
847
+ end
848
+
849
+ it "returns true" do
850
+ expect(person).to be_changed
851
+ end
852
+ end
853
+
854
+ context "when adding via create" do
855
+
856
+ before do
857
+ address.locations.create
858
+ end
859
+
860
+ it "returns false" do
861
+ expect(person).to_not be_changed
862
+ end
863
+ end
864
+ end
865
+
796
866
  context "when a deeply embedded child has changed" do
797
867
 
798
868
  let(:person) do
@@ -1555,4 +1625,90 @@ describe Mongoid::Changeable do
1555
1625
  expect(person.setters).to_not eq({ "addresses" => nil })
1556
1626
  end
1557
1627
  end
1628
+
1629
+ context 'when nesting deeply embedded documents' do
1630
+
1631
+ context 'when persisting the root document' do
1632
+
1633
+ let!(:person) do
1634
+ Person.create
1635
+ end
1636
+
1637
+ it 'is not marked as changed' do
1638
+ expect(person).to_not be_changed
1639
+ end
1640
+
1641
+ context 'when creating a new first level embedded document' do
1642
+
1643
+ let!(:address) do
1644
+ person.addresses.new(street: 'goltzstr.')
1645
+ end
1646
+
1647
+ it 'flags the root document as changed' do
1648
+ expect(person).to be_changed
1649
+ end
1650
+
1651
+ it 'flags the first level child as changed' do
1652
+ expect(address).to be_changed
1653
+ end
1654
+
1655
+ context 'when building the lowest level document' do
1656
+
1657
+ before do
1658
+ person.save
1659
+ end
1660
+
1661
+ let!(:code) do
1662
+ address.build_code
1663
+ end
1664
+
1665
+ it 'flags the root document as changed' do
1666
+ expect(person).to be_changed
1667
+ end
1668
+
1669
+ it 'flags the first level embedded document as changed' do
1670
+ expect(address).to be_changed
1671
+ end
1672
+
1673
+ it 'flags the lowest level embedded document as changed' do
1674
+ expect(code).to be_changed
1675
+ end
1676
+
1677
+ context 'when saving the hierarchy' do
1678
+
1679
+ before do
1680
+ person.save
1681
+ end
1682
+
1683
+ let(:reloaded) do
1684
+ Person.find(person.id)
1685
+ end
1686
+
1687
+ it 'saves the first embedded document' do
1688
+ expect(reloaded.addresses.first).to eq(address)
1689
+ end
1690
+
1691
+ it 'saves the lowest level embedded document' do
1692
+ expect(reloaded.addresses.first.code).to eq(code)
1693
+ end
1694
+
1695
+ context 'when embedding further' do
1696
+
1697
+ let!(:deepest) do
1698
+ reloaded.addresses.first.code.build_deepest
1699
+ end
1700
+
1701
+ before do
1702
+ reloaded.save
1703
+ end
1704
+
1705
+ it 'saves the deepest embedded document' do
1706
+ expect(reloaded.reload.addresses.first.code.deepest).to eq(deepest)
1707
+ end
1708
+ end
1709
+ end
1710
+ end
1711
+ end
1712
+ end
1713
+ end
1558
1714
  end
@@ -0,0 +1,284 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Clients::Factory do
4
+
5
+ describe ".create" do
6
+
7
+ context "when provided a name" do
8
+
9
+ context "when the configuration exists" do
10
+
11
+ context "when the configuration is standard" do
12
+
13
+ let(:config) do
14
+ {
15
+ default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
16
+ secondary: { hosts: [ "127.0.0.1:27017" ], database: database_id }
17
+ }
18
+ end
19
+
20
+ before do
21
+ Mongoid::Config.send(:clients=, config)
22
+ end
23
+
24
+ let(:client) do
25
+ described_class.create(:secondary)
26
+ end
27
+
28
+ let(:cluster) do
29
+ client.cluster
30
+ end
31
+
32
+ it "returns a client" do
33
+ expect(client).to be_a(Mongo::Client)
34
+ end
35
+
36
+ it "sets the cluster's seeds" do
37
+ expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
38
+ end
39
+ end
40
+
41
+ context "when the configuration has no ports" do
42
+
43
+ let(:config) do
44
+ {
45
+ default: { hosts: [ "127.0.0.1" ], database: database_id },
46
+ secondary: { hosts: [ "127.0.0.1" ], database: database_id }
47
+ }
48
+ end
49
+
50
+ before do
51
+ Mongoid::Config.send(:clients=, config)
52
+ end
53
+
54
+ let(:client) do
55
+ described_class.create(:secondary)
56
+ end
57
+
58
+ let(:default) do
59
+ described_class.create(:default)
60
+ end
61
+
62
+ let(:cluster) do
63
+ client.cluster
64
+ end
65
+
66
+ it "returns a client" do
67
+ expect(client).to be_a(Mongo::Client)
68
+ end
69
+
70
+ it "sets the cluster's seed ports to 27017" do
71
+ expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
72
+ end
73
+
74
+ it "sets ips with no ports to 27017" do
75
+ expect(default.cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
76
+ end
77
+ end
78
+
79
+ context "when configured via a uri" do
80
+
81
+ context "when the uri has a single host:port" do
82
+
83
+ let(:config) do
84
+ {
85
+ default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
86
+ secondary: { uri: "mongodb://127.0.0.1:27017/mongoid_test" }
87
+ }
88
+ end
89
+
90
+ before do
91
+ Mongoid::Config.send(:clients=, config)
92
+ end
93
+
94
+ let(:client) do
95
+ described_class.create(:secondary)
96
+ end
97
+
98
+ let(:cluster) do
99
+ client.cluster
100
+ end
101
+
102
+ it "returns a client" do
103
+ expect(client).to be_a(Mongo::Client)
104
+ end
105
+
106
+ it "sets the cluster's seeds" do
107
+ expect(cluster.addresses.first.to_s).to eq("127.0.0.1:27017")
108
+ end
109
+
110
+ it "sets the database" do
111
+ expect(client.options[:database]).to eq("mongoid_test")
112
+ end
113
+ end
114
+
115
+ context "when the uri has multiple host:port pairs" do
116
+
117
+ let(:config) do
118
+ {
119
+ default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
120
+ secondary: { uri: "mongodb://127.0.0.1:27017,127.0.0.1:27018/mongoid_test" }
121
+ }
122
+ end
123
+
124
+ before do
125
+ Mongoid::Config.send(:clients=, config)
126
+ end
127
+
128
+ let(:client) do
129
+ described_class.create(:secondary)
130
+ end
131
+
132
+ let(:cluster) do
133
+ client.cluster
134
+ end
135
+
136
+ let(:seeds) do
137
+ cluster.addresses.map{ |address| address.to_s }
138
+ end
139
+
140
+ it "returns a client" do
141
+ expect(client).to be_a(Mongo::Client)
142
+ end
143
+
144
+ it "sets the cluster's seeds" do
145
+ expect(seeds).to eq([ "127.0.0.1:27017", "127.0.0.1:27018" ])
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ context "when the configuration does not exist" do
152
+
153
+ it "raises an error" do
154
+ expect {
155
+ described_class.create(:unknown)
156
+ }.to raise_error(Mongoid::Errors::NoClientConfig)
157
+ end
158
+ end
159
+ end
160
+
161
+ context "when no name is provided" do
162
+
163
+ let(:config) do
164
+ { default: { hosts: ["127.0.0.1:27017"], database: database_id }}
165
+ end
166
+
167
+ before do
168
+ Mongoid::Config.send(:clients=, config)
169
+ end
170
+
171
+ let(:client) do
172
+ described_class.create
173
+ end
174
+
175
+ let(:cluster) do
176
+ client.cluster
177
+ end
178
+
179
+ let(:seeds) do
180
+ cluster.addresses.map{ |address| address.to_s }
181
+ end
182
+
183
+ it "returns the default client" do
184
+ expect(client).to be_a(Mongo::Client)
185
+ end
186
+
187
+ it "sets the cluster's seeds" do
188
+ expect(seeds).to eq([ "127.0.0.1:27017" ])
189
+ end
190
+ end
191
+
192
+ context "when nil is provided and no default config" do
193
+
194
+ let(:config) { nil }
195
+
196
+ before do
197
+ Mongoid.clients[:default] = nil
198
+ end
199
+
200
+ it "raises NoClientsConfig error" do
201
+ expect{ Mongoid::Clients::Factory.create(config) }.to raise_error(Mongoid::Errors::NoClientsConfig)
202
+ end
203
+ end
204
+ end
205
+
206
+ describe ".default" do
207
+
208
+ let(:config) do
209
+ { default: { hosts: ["127.0.0.1:27017"], database: database_id }}
210
+ end
211
+
212
+ before do
213
+ Mongoid::Config.send(:clients=, config)
214
+ end
215
+
216
+ let(:client) do
217
+ described_class.default
218
+ end
219
+
220
+ let(:cluster) do
221
+ client.cluster
222
+ end
223
+
224
+ let(:seeds) do
225
+ cluster.addresses.map{ |address| address.to_s }
226
+ end
227
+
228
+ it "returns the default client" do
229
+ expect(client).to be_a(Mongo::Client)
230
+ end
231
+
232
+ it "sets the cluster's seeds" do
233
+ expect(seeds).to eq([ "127.0.0.1:27017" ])
234
+ end
235
+ end
236
+
237
+ context "when options are provided with string keys" do
238
+
239
+ let(:config) do
240
+ {
241
+ default: {
242
+ hosts: [ "127.0.0.1:27017" ],
243
+ database: database_id,
244
+ options: {
245
+ "server_selection_timeout" => 10,
246
+ "write" => { "w" => 1 }
247
+ }
248
+ }
249
+ }
250
+ end
251
+
252
+ before do
253
+ Mongoid::Config.send(:clients=, config)
254
+ end
255
+
256
+ let(:client) do
257
+ described_class.default
258
+ end
259
+
260
+ let(:cluster) do
261
+ client.cluster
262
+ end
263
+
264
+ let(:seeds) do
265
+ cluster.addresses.map{ |address| address.to_s }
266
+ end
267
+
268
+ it "returns the default client" do
269
+ expect(client).to be_a(Mongo::Client)
270
+ end
271
+
272
+ it "sets the cluster's seeds" do
273
+ expect(seeds).to eq([ "127.0.0.1:27017" ])
274
+ end
275
+
276
+ it "sets the server selection timeout" do
277
+ expect(cluster.options[:server_selection_timeout]).to eq(10)
278
+ end
279
+
280
+ it "sets the write concern" do
281
+ expect(client.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
282
+ end
283
+ end
284
+ end