mongoid 4.0.2 → 5.0.0.beta

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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/README.md +14 -13
  4. data/lib/config/locales/en.yml +28 -28
  5. data/lib/mongoid.rb +28 -21
  6. data/lib/mongoid/atomic.rb +2 -4
  7. data/lib/mongoid/attributes.rb +7 -7
  8. data/lib/mongoid/attributes/processing.rb +4 -1
  9. data/lib/mongoid/attributes/readonly.rb +2 -2
  10. data/lib/mongoid/changeable.rb +4 -6
  11. data/lib/mongoid/clients.rb +142 -0
  12. data/lib/mongoid/clients/factory.rb +78 -0
  13. data/lib/mongoid/{sessions → clients}/options.rb +30 -19
  14. data/lib/mongoid/{sessions → clients}/storage_options.rb +27 -13
  15. data/lib/mongoid/{sessions → clients}/thread_options.rb +6 -3
  16. data/lib/mongoid/clients/validators.rb +2 -0
  17. data/lib/mongoid/{sessions → clients}/validators/storage.rb +5 -2
  18. data/lib/mongoid/composable.rb +3 -3
  19. data/lib/mongoid/config.rb +39 -41
  20. data/lib/mongoid/config/environment.rb +1 -1
  21. data/lib/mongoid/config/validators.rb +1 -1
  22. data/lib/mongoid/config/validators/{session.rb → client.rb} +31 -28
  23. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  24. data/lib/mongoid/contextual/atomic.rb +11 -11
  25. data/lib/mongoid/contextual/command.rb +9 -6
  26. data/lib/mongoid/contextual/geo_near.rb +17 -1
  27. data/lib/mongoid/contextual/map_reduce.rb +12 -11
  28. data/lib/mongoid/contextual/memory.rb +2 -5
  29. data/lib/mongoid/contextual/mongo.rb +92 -82
  30. data/lib/mongoid/contextual/none.rb +13 -0
  31. data/lib/mongoid/copyable.rb +6 -1
  32. data/lib/mongoid/criteria.rb +36 -3
  33. data/lib/mongoid/document.rb +3 -4
  34. data/lib/mongoid/errors.rb +6 -6
  35. data/lib/mongoid/errors/{mixed_session_configuration.rb → mixed_client_configuration.rb} +5 -5
  36. data/lib/mongoid/errors/no_client_config.rb +22 -0
  37. data/lib/mongoid/errors/{no_session_database.rb → no_client_database.rb} +4 -4
  38. data/lib/mongoid/errors/{no_session_hosts.rb → no_client_hosts.rb} +4 -4
  39. data/lib/mongoid/errors/{no_sessions_config.rb → no_clients_config.rb} +4 -4
  40. data/lib/mongoid/errors/no_default_client.rb +23 -0
  41. data/lib/mongoid/extensions/hash.rb +5 -1
  42. data/lib/mongoid/extensions/object.rb +3 -2
  43. data/lib/mongoid/extensions/set.rb +5 -5
  44. data/lib/mongoid/factory.rb +4 -2
  45. data/lib/mongoid/fields.rb +7 -2
  46. data/lib/mongoid/findable.rb +4 -1
  47. data/lib/mongoid/indexable.rb +15 -9
  48. data/lib/mongoid/persistable.rb +1 -2
  49. data/lib/mongoid/persistable/creatable.rb +2 -2
  50. data/lib/mongoid/persistable/deletable.rb +3 -3
  51. data/lib/mongoid/persistable/incrementable.rb +1 -1
  52. data/lib/mongoid/persistable/logical.rb +1 -1
  53. data/lib/mongoid/persistable/poppable.rb +1 -1
  54. data/lib/mongoid/persistable/pullable.rb +2 -2
  55. data/lib/mongoid/persistable/pushable.rb +2 -2
  56. data/lib/mongoid/persistable/renamable.rb +1 -1
  57. data/lib/mongoid/persistable/settable.rb +1 -1
  58. data/lib/mongoid/persistable/unsettable.rb +1 -1
  59. data/lib/mongoid/persistable/updatable.rb +2 -2
  60. data/lib/mongoid/persistable/upsertable.rb +1 -1
  61. data/lib/mongoid/query_cache.rb +98 -104
  62. data/lib/mongoid/railtie.rb +1 -21
  63. data/lib/mongoid/railties/database.rake +1 -1
  64. data/lib/mongoid/relations/builders.rb +3 -1
  65. data/lib/mongoid/relations/counter_cache.rb +1 -1
  66. data/lib/mongoid/relations/embedded/batchable.rb +3 -10
  67. data/lib/mongoid/relations/embedded/many.rb +4 -2
  68. data/lib/mongoid/relations/many.rb +1 -0
  69. data/lib/mongoid/relations/proxy.rb +6 -6
  70. data/lib/mongoid/relations/referenced/many.rb +2 -1
  71. data/lib/mongoid/relations/targets/enumerable.rb +11 -11
  72. data/lib/mongoid/relations/touchable.rb +1 -1
  73. data/lib/mongoid/reloadable.rb +2 -2
  74. data/lib/mongoid/scopable.rb +6 -17
  75. data/lib/mongoid/selectable.rb +1 -36
  76. data/lib/mongoid/serializable.rb +2 -2
  77. data/lib/mongoid/stateful.rb +0 -1
  78. data/lib/mongoid/tasks/database.rake +2 -2
  79. data/lib/mongoid/tasks/database.rb +23 -16
  80. data/lib/mongoid/threaded.rb +54 -33
  81. data/lib/mongoid/threaded/lifecycle.rb +21 -16
  82. data/lib/mongoid/traversable.rb +16 -1
  83. data/lib/mongoid/validatable.rb +1 -1
  84. data/lib/mongoid/validatable/queryable.rb +1 -1
  85. data/lib/mongoid/validatable/uniqueness.rb +3 -20
  86. data/lib/mongoid/version.rb +1 -1
  87. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +91 -57
  88. data/lib/rails/mongoid.rb +2 -2
  89. data/spec/app/models/audio.rb +1 -1
  90. data/spec/app/models/band.rb +1 -0
  91. data/spec/app/models/company.rb +5 -0
  92. data/spec/app/models/label.rb +7 -0
  93. data/spec/app/models/pub.rb +6 -0
  94. data/spec/app/models/staff.rb +7 -0
  95. data/spec/app/models/store_as_dup_test1.rb +5 -0
  96. data/spec/app/models/store_as_dup_test2.rb +5 -0
  97. data/spec/config/mongoid.yml +7 -25
  98. data/spec/mongoid/atomic/paths_spec.rb +3 -11
  99. data/spec/mongoid/attributes/nested_spec.rb +16 -16
  100. data/spec/mongoid/attributes/readonly_spec.rb +80 -18
  101. data/spec/mongoid/attributes_spec.rb +3 -3
  102. data/spec/mongoid/changeable_spec.rb +70 -0
  103. data/spec/mongoid/clients/factory_spec.rb +284 -0
  104. data/spec/mongoid/{sessions → clients}/options_spec.rb +4 -6
  105. data/spec/mongoid/clients_spec.rb +739 -0
  106. data/spec/mongoid/config/environment_spec.rb +14 -11
  107. data/spec/mongoid/config_spec.rb +33 -48
  108. data/spec/mongoid/contextual/atomic_spec.rb +1 -17
  109. data/spec/mongoid/contextual/geo_near_spec.rb +35 -0
  110. data/spec/mongoid/contextual/mongo_spec.rb +26 -83
  111. data/spec/mongoid/contextual/none_spec.rb +15 -0
  112. data/spec/mongoid/copyable_spec.rb +35 -1
  113. data/spec/mongoid/criteria/findable_spec.rb +197 -0
  114. data/spec/mongoid/criteria/modifiable_spec.rb +7 -29
  115. data/spec/mongoid/criteria_spec.rb +74 -91
  116. data/spec/mongoid/document_spec.rb +1 -1
  117. data/spec/mongoid/errors/{mixed_session_configuration_spec.rb → mixed_client_configuration_spec.rb} +1 -1
  118. data/spec/mongoid/errors/{no_session_config_spec.rb → no_client_config_spec.rb} +4 -4
  119. data/spec/mongoid/errors/{no_session_database_spec.rb → no_client_database_spec.rb} +4 -4
  120. data/spec/mongoid/errors/{no_session_hosts_spec.rb → no_client_hosts_spec.rb} +3 -3
  121. data/spec/mongoid/errors/{no_sessions_config_spec.rb → no_clients_config_spec.rb} +2 -2
  122. data/spec/mongoid/fields/localized_spec.rb +1 -0
  123. data/spec/mongoid/fields_spec.rb +1 -0
  124. data/spec/mongoid/findable_spec.rb +2 -23
  125. data/spec/mongoid/indexable_spec.rb +12 -8
  126. data/spec/mongoid/interceptable_spec.rb +15 -0
  127. data/spec/mongoid/persistable/settable_spec.rb +16 -0
  128. data/spec/mongoid/persistable/updatable_spec.rb +3 -2
  129. data/spec/mongoid/persistable_spec.rb +4 -4
  130. data/spec/mongoid/query_cache_spec.rb +13 -8
  131. data/spec/mongoid/relations/auto_save_spec.rb +1 -1
  132. data/spec/mongoid/relations/counter_cache_spec.rb +34 -0
  133. data/spec/mongoid/relations/eager/belongs_to_spec.rb +9 -0
  134. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +3 -3
  135. data/spec/mongoid/relations/embedded/many_spec.rb +123 -1
  136. data/spec/mongoid/relations/embedded/one_spec.rb +3 -3
  137. data/spec/mongoid/relations/proxy_spec.rb +28 -0
  138. data/spec/mongoid/relations/referenced/in_spec.rb +1 -1
  139. data/spec/mongoid/relations/referenced/many_spec.rb +47 -23
  140. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +1 -1
  141. data/spec/mongoid/relations/referenced/one_spec.rb +1 -1
  142. data/spec/mongoid/relations/targets/enumerable_spec.rb +9 -2
  143. data/spec/mongoid/reloadable_spec.rb +6 -6
  144. data/spec/mongoid/scopable_spec.rb +41 -28
  145. data/spec/mongoid/selectable_spec.rb +6 -16
  146. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  147. data/spec/mongoid/tasks/database_spec.rb +2 -2
  148. data/spec/mongoid/threaded_spec.rb +0 -7
  149. data/spec/mongoid/traversable_spec.rb +2 -2
  150. data/spec/mongoid/validatable/uniqueness_spec.rb +30 -1
  151. data/spec/mongoid_spec.rb +13 -15
  152. data/spec/rails/mongoid_spec.rb +13 -4
  153. data/spec/spec_helper.rb +44 -27
  154. data/spec/support/authorization.rb +12 -0
  155. data/spec/support/expectations.rb +14 -0
  156. metadata +52 -59
  157. data/lib/mongoid/contextual/find_and_modify.rb +0 -69
  158. data/lib/mongoid/contextual/text_search.rb +0 -178
  159. data/lib/mongoid/criteria/#findable.rb# +0 -141
  160. data/lib/mongoid/errors/no_default_session.rb +0 -23
  161. data/lib/mongoid/errors/no_session_config.rb +0 -22
  162. data/lib/mongoid/log_subscriber.rb +0 -55
  163. data/lib/mongoid/positional.rb +0 -71
  164. data/lib/mongoid/sessions.rb +0 -125
  165. data/lib/mongoid/sessions/factory.rb +0 -131
  166. data/lib/mongoid/sessions/mongo_uri.rb +0 -93
  167. data/lib/mongoid/sessions/validators.rb +0 -2
  168. data/lib/mongoid/support/query_counter.rb +0 -23
  169. data/spec/helpers.rb +0 -18
  170. data/spec/mongoid/#atomic_spec.rb# +0 -365
  171. data/spec/mongoid/contextual/find_and_modify_spec.rb +0 -220
  172. data/spec/mongoid/contextual/text_search_spec.rb +0 -209
  173. data/spec/mongoid/log_subscriber_spec.rb +0 -75
  174. data/spec/mongoid/positional_spec.rb +0 -222
  175. data/spec/mongoid/sessions/factory_spec.rb +0 -333
  176. data/spec/mongoid/sessions/mongo_uri_spec.rb +0 -103
  177. data/spec/mongoid/sessions_spec.rb +0 -1252
@@ -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
@@ -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
@@ -1,8 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Mongoid::Sessions::Options do
3
+ describe Mongoid::Clients::Options do
4
4
 
5
- describe "#with" do
5
+ describe "#with", if: non_legacy_server? do
6
6
 
7
7
  context "when passing some options" do
8
8
 
@@ -52,7 +52,7 @@ describe Mongoid::Sessions::Options do
52
52
  end
53
53
  end
54
54
 
55
- describe ".with" do
55
+ describe ".with", if: non_legacy_server? do
56
56
 
57
57
  let(:options) { { database: 'test' } }
58
58
 
@@ -65,9 +65,7 @@ describe Mongoid::Sessions::Options do
65
65
  end
66
66
 
67
67
  it "passes down the options to collection" do
68
- session = Band.mongo_session
69
- expect_any_instance_of(Moped::Session).to receive(:with).with(options).and_return(session)
70
- instance.collection
68
+ expect(instance.collection.database.name).to eq('test')
71
69
  end
72
70
  end
73
71
 
@@ -0,0 +1,739 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Clients do
4
+
5
+ describe "#collection" do
6
+
7
+ shared_examples_for "an overridden collection at the class level" do
8
+
9
+ let(:band) do
10
+ klass.new
11
+ end
12
+
13
+ it "returns the collection for the model" do
14
+ expect(band.collection).to be_a(Mongo::Collection)
15
+ end
16
+
17
+ it "sets the correct collection name" do
18
+ expect(band.collection.name).to eq("artists")
19
+ end
20
+
21
+ context "when accessing from the class level" do
22
+
23
+ it "returns the collection for the model" do
24
+ expect(klass.collection).to be_a(Mongo::Collection)
25
+ end
26
+
27
+ it "sets the correct collection name" do
28
+ expect(klass.collection.name).to eq("artists")
29
+ end
30
+ end
31
+ end
32
+
33
+ context "when overriding the persistence options" do
34
+
35
+ let(:klass) do
36
+ Band.with(collection: "artists")
37
+ end
38
+
39
+ it_behaves_like "an overridden collection at the class level"
40
+ end
41
+
42
+ context "when overriding store_in and persistence options" do
43
+
44
+ let(:klass) do
45
+ Band.with(collection: "artists")
46
+ end
47
+
48
+ before do
49
+ Band.store_in collection: "foo"
50
+ end
51
+
52
+ after do
53
+ Band.reset_storage_options!
54
+ end
55
+
56
+ it_behaves_like "an overridden collection at the class level"
57
+ end
58
+
59
+ context "when overriding the default with store_in" do
60
+
61
+ after do
62
+ Band.reset_storage_options!
63
+ end
64
+
65
+ context "when called multiple times with different options" do
66
+
67
+ before do
68
+ Band.store_in collection: "artists"
69
+ Band.store_in client: "another"
70
+ end
71
+
72
+ it "should merge the options together" do
73
+ expect(Band.storage_options[:collection]).to eq("artists")
74
+ expect(Band.storage_options[:client]).to eq("another")
75
+ end
76
+ end
77
+
78
+ context "when overriding with a proc" do
79
+
80
+ let(:klass) { Band }
81
+
82
+ before do
83
+ Band.store_in(collection: ->{ "artists" })
84
+ end
85
+
86
+ it_behaves_like "an overridden collection at the class level"
87
+ end
88
+
89
+ context "when overriding with a string" do
90
+
91
+ let(:klass) { Band }
92
+
93
+ before do
94
+ Band.store_in(collection: "artists")
95
+ end
96
+
97
+ after do
98
+ Band.reset_storage_options!
99
+ end
100
+
101
+ it_behaves_like "an overridden collection at the class level"
102
+ end
103
+
104
+ context "when overriding with a symbol" do
105
+
106
+ let(:klass) { Band }
107
+
108
+ before do
109
+ klass.store_in(collection: :artists)
110
+ end
111
+
112
+ after do
113
+ klass.reset_storage_options!
114
+ end
115
+
116
+ it_behaves_like "an overridden collection at the class level"
117
+ end
118
+ end
119
+
120
+ context "when not overriding the default" do
121
+
122
+ let(:band) do
123
+ Band.new
124
+ end
125
+
126
+ it "returns the collection for the model" do
127
+ expect(band.collection).to be_a(Mongo::Collection)
128
+ end
129
+
130
+ it "sets the correct collection name" do
131
+ expect(band.collection.name.to_s).to eq("bands")
132
+ end
133
+
134
+ context "when accessing from the class level" do
135
+
136
+ it "returns the collection for the model" do
137
+ expect(Band.collection).to be_a(Mongo::Collection)
138
+ end
139
+
140
+ it "sets the correct collection name" do
141
+ expect(Band.collection.name.to_s).to eq("bands")
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#collection_name" do
148
+
149
+ shared_examples_for "an overridden collection name at the class level" do
150
+
151
+ let(:band) do
152
+ klass.new
153
+ end
154
+
155
+ context "when accessing from the instance" do
156
+
157
+ it "returns the overridden value" do
158
+ expect(band.collection_name).to eq(:artists)
159
+ end
160
+ end
161
+
162
+ context "when accessing from the class level" do
163
+
164
+ it "returns the overridden value" do
165
+ expect(klass.collection_name).to eq(:artists)
166
+ end
167
+ end
168
+ end
169
+
170
+ context "when overriding the persistence options" do
171
+
172
+ let(:klass) do
173
+ Band.with(collection: "artists")
174
+ end
175
+
176
+ it_behaves_like "an overridden collection name at the class level"
177
+ end
178
+
179
+ context "when overriding store_in and persistence options" do
180
+
181
+ let(:klass) do
182
+ Band.with(collection: "artists")
183
+ end
184
+
185
+ before do
186
+ Band.store_in collection: "foo"
187
+ end
188
+
189
+ after do
190
+ Band.reset_storage_options!
191
+ end
192
+
193
+ it_behaves_like "an overridden collection name at the class level"
194
+ end
195
+
196
+ context "when overriding the default with store_in" do
197
+
198
+ let(:klass) { Band }
199
+
200
+ after do
201
+ Band.reset_storage_options!
202
+ end
203
+
204
+ context "when overriding with a proc" do
205
+
206
+ before do
207
+ Band.store_in(collection: ->{ "artists" })
208
+ end
209
+
210
+ it_behaves_like "an overridden collection name at the class level"
211
+ end
212
+
213
+ context "when overriding with a string" do
214
+
215
+ before do
216
+ Band.store_in(collection: "artists")
217
+ end
218
+
219
+ it_behaves_like "an overridden collection name at the class level"
220
+ end
221
+
222
+ context "when overriding with a symbol" do
223
+
224
+ before do
225
+ Band.store_in(collection: :artists)
226
+ end
227
+
228
+ it_behaves_like "an overridden collection name at the class level"
229
+ end
230
+ end
231
+
232
+ context "when not overriding the default" do
233
+
234
+ let(:band) do
235
+ Band.new
236
+ end
237
+
238
+ it "returns the pluralized model name" do
239
+ expect(band.collection_name).to eq(:bands)
240
+ end
241
+
242
+ context "when accessing from the class level" do
243
+
244
+ it "returns the pluralized model name" do
245
+ expect(Band.collection_name).to eq(:bands)
246
+ end
247
+ end
248
+ end
249
+
250
+ context "when the model is a subclass" do
251
+
252
+ let(:firefox) do
253
+ Firefox.new
254
+ end
255
+
256
+ it "returns the root class pluralized model name" do
257
+ expect(firefox.collection_name).to eq(:canvases)
258
+ end
259
+
260
+ context "when accessing from the class level" do
261
+
262
+ it "returns the root class pluralized model name" do
263
+ expect(Firefox.collection_name).to eq(:canvases)
264
+ end
265
+ end
266
+ end
267
+ end
268
+
269
+ describe "#database_name", if: non_legacy_server? do
270
+
271
+ shared_examples_for "an overridden database name" do
272
+
273
+ let(:band) do
274
+ klass.new
275
+ end
276
+
277
+ context "when accessing from the instance" do
278
+
279
+ it "returns the overridden value" do
280
+ # @todo
281
+ # expect(band.mongo_client.options[:database].to_s).to eq(database_id_alt)
282
+ end
283
+ end
284
+
285
+ context "when accessing from the class level" do
286
+
287
+ it "returns the overridden value" do
288
+ expect(klass.database_name.to_s).to eq(database_id_alt)
289
+ end
290
+
291
+ it "client returns the overridden value" do
292
+ expect(klass.mongo_client.options[:database].to_s).to eq(database_id_alt)
293
+ end
294
+ end
295
+ end
296
+
297
+ context "when overriding the persistence options" do
298
+
299
+ let(:klass) do
300
+ Band.with(database: database_id_alt)
301
+ end
302
+
303
+ it_behaves_like "an overridden database name"
304
+ end
305
+
306
+ context "when overriding with store_in" do
307
+
308
+ let(:klass) { Band }
309
+
310
+ before do
311
+ Band.store_in database: database_id_alt
312
+ end
313
+
314
+ after do
315
+ Band.reset_storage_options!
316
+ end
317
+
318
+ it_behaves_like "an overridden database name"
319
+ end
320
+
321
+ context "when overriding store_in and persistence options" do
322
+
323
+ let(:klass) do
324
+ Band.with(database: database_id_alt)
325
+ end
326
+
327
+ before do
328
+ Band.store_in database: "foo"
329
+ end
330
+
331
+ after do
332
+ Band.reset_storage_options!
333
+ end
334
+
335
+ it_behaves_like "an overridden database name"
336
+ end
337
+
338
+ context "when overriding using the client" do
339
+
340
+ let(:client_name) { :alternative }
341
+
342
+ before do
343
+ Mongoid.clients[client_name] = { database: database_id_alt, hosts: [ "#{HOST}:#{PORT}" ] }
344
+ end
345
+
346
+ after do
347
+ Mongoid.clients.delete(client_name)
348
+ end
349
+
350
+ context "when overriding the persistence options" do
351
+
352
+ let(:klass) do
353
+ Band.with(client: client_name)
354
+ end
355
+
356
+ it_behaves_like "an overridden database name"
357
+ end
358
+
359
+ context "when overriding with store_in" do
360
+
361
+ let(:klass) { Band }
362
+
363
+ before do
364
+ Band.store_in(client: client_name)
365
+ end
366
+
367
+ after do
368
+ Band.reset_storage_options!
369
+ end
370
+
371
+ it_behaves_like "an overridden database name"
372
+ end
373
+ end
374
+ end
375
+
376
+ describe "#mongo_client", if: non_legacy_server? do
377
+
378
+ let(:file) do
379
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
380
+ end
381
+
382
+ before do
383
+ described_class.clear
384
+ Mongoid.load!(file, :test)
385
+ Mongoid.clients[:default][:database] = database_id
386
+ end
387
+
388
+ context "when getting the default" do
389
+
390
+ let(:file) do
391
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
392
+ end
393
+
394
+ before do
395
+ described_class.clear
396
+ Mongoid.load!(file, :test)
397
+ Mongoid.clients[:default][:database] = database_id
398
+ end
399
+
400
+ let!(:band) do
401
+ Band.new
402
+ end
403
+
404
+ let!(:mongo_client) do
405
+ band.mongo_client
406
+ end
407
+
408
+ it "returns the default client" do
409
+ expect(mongo_client.options[:database].to_s).to eq(database_id)
410
+ end
411
+ end
412
+
413
+ context "when no client exists with the key" do
414
+
415
+ before(:all) do
416
+ Band.store_in(client: :nonexistant)
417
+ end
418
+
419
+ let(:band) do
420
+ Band.new
421
+ end
422
+
423
+ it "raises an error" do
424
+ expect {
425
+ band.mongo_client
426
+ }.to raise_error(Mongoid::Errors::NoClientConfig)
427
+ end
428
+ end
429
+ end
430
+
431
+ describe ".mongo_client", if: non_legacy_server? do
432
+
433
+ let(:file) do
434
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
435
+ end
436
+
437
+ before do
438
+ described_class.clear
439
+ Mongoid.load!(file, :test)
440
+ Mongoid.clients[:default][:database] = database_id
441
+ end
442
+
443
+ after do
444
+ Band.reset_storage_options!
445
+ end
446
+
447
+ context "when getting the default" do
448
+
449
+ let(:file) do
450
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
451
+ end
452
+
453
+ before do
454
+ Band.reset_storage_options!
455
+ described_class.clear
456
+ Mongoid.load!(file, :test)
457
+ Mongoid.clients[:default][:database] = database_id
458
+ end
459
+
460
+ let!(:mongo_client) do
461
+ Band.mongo_client
462
+ end
463
+
464
+ it "returns the default client" do
465
+ expect(mongo_client.options[:database].to_s).to eq(database_id)
466
+ end
467
+ end
468
+
469
+ context "when no client exists with the key" do
470
+
471
+ before(:all) do
472
+ Band.store_in(client: :nonexistant)
473
+ end
474
+
475
+ it "raises an error" do
476
+ expect {
477
+ Band.mongo_client
478
+ }.to raise_error(Mongoid::Errors::NoClientConfig)
479
+ end
480
+ end
481
+ end
482
+
483
+ describe ".store_in", if: non_legacy_server? do
484
+
485
+ context "when provided a non hash" do
486
+
487
+ it "raises an error" do
488
+ expect {
489
+ Band.store_in :artists
490
+ }.to raise_error(Mongoid::Errors::InvalidStorageOptions)
491
+ end
492
+ end
493
+
494
+ context "when provided a class that extend another document" do
495
+
496
+ let(:klass) do
497
+ Class.new(Band)
498
+ end
499
+
500
+ it "raises an error" do
501
+ expect {
502
+ klass.store_in(database: :artists)
503
+ }.to raise_error(Mongoid::Errors::InvalidStorageParent)
504
+ end
505
+ end
506
+
507
+ context "when provided a hash" do
508
+
509
+ context "when the hash is not valid" do
510
+
511
+ it "raises an error" do
512
+ expect {
513
+ Band.store_in coll: "artists"
514
+ }.to raise_error(Mongoid::Errors::InvalidStorageOptions)
515
+ end
516
+ end
517
+ end
518
+ end
519
+
520
+ describe ".with", if: non_legacy_server? do
521
+
522
+ context "when sending operations to a different database" do
523
+
524
+ after do
525
+ Band.with(database: database_id_alt).delete_all
526
+ end
527
+
528
+ describe ".create" do
529
+
530
+ let!(:band) do
531
+ Band.with(database: database_id_alt).create
532
+ end
533
+
534
+ it "does not persist to the default database" do
535
+ expect {
536
+ Band.find(band.id)
537
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
538
+ end
539
+
540
+ let(:from_db) do
541
+ Band.with(database: database_id_alt).find(band.id)
542
+ end
543
+
544
+ it "persists to the specified database" do
545
+ expect(from_db).to eq(band)
546
+ end
547
+
548
+ it "persists the correct number of documents" do
549
+ expect(Band.with(database: database_id_alt).count).to eq(1)
550
+ end
551
+ end
552
+ end
553
+
554
+ context "when sending operations to a different collection" do
555
+
556
+ describe ".create" do
557
+
558
+ let!(:band) do
559
+ Band.with(collection: "artists").create
560
+ end
561
+
562
+ it "does not persist to the default database" do
563
+ expect {
564
+ Band.find(band.id)
565
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
566
+ end
567
+
568
+ let(:from_db) do
569
+ Band.with(collection: "artists").find(band.id)
570
+ end
571
+
572
+ it "persists to the specified database" do
573
+ expect(from_db).to eq(band)
574
+ end
575
+
576
+ it "persists the correct number of documents" do
577
+ expect(Band.with(collection: "artists").count).to eq(1)
578
+ end
579
+ end
580
+ end
581
+
582
+ context "when sending operations with safe mode" do
583
+
584
+ describe ".create" do
585
+
586
+ before do
587
+ Person.create_indexes
588
+ Person.create(ssn: "432-97-1111")
589
+ end
590
+
591
+ context "when no error occurs" do
592
+
593
+ it "inserts the document" do
594
+ expect(Person.count).to eq(1)
595
+ end
596
+ end
597
+
598
+ context "when a mongodb error occurs" do
599
+
600
+ it "bubbles up to the caller" do
601
+ expect {
602
+ Person.create(ssn: "432-97-1111")
603
+ }.to raise_error(Mongo::Error::OperationFailure)
604
+ end
605
+ end
606
+ end
607
+
608
+ describe ".create!" do
609
+
610
+ before do
611
+ Person.create!(ssn: "432-97-1112")
612
+ end
613
+
614
+ context "when no error occurs" do
615
+
616
+ it "inserts the document" do
617
+ expect(Person.count).to eq(1)
618
+ end
619
+ end
620
+
621
+ context "when a mongodb error occurs" do
622
+
623
+ before do
624
+ Person.create_indexes
625
+ end
626
+
627
+ it "bubbles up to the caller" do
628
+ expect {
629
+ Person.create!(ssn: "432-97-1112")
630
+ }.to raise_error(Mongo::Error::OperationFailure)
631
+ end
632
+ end
633
+
634
+ context "when a validation error occurs" do
635
+
636
+ it "raises the validation error" do
637
+ expect {
638
+ Account.create!(name: "this name is way too long")
639
+ }.to raise_error(Mongoid::Errors::Validations)
640
+ end
641
+ end
642
+ end
643
+
644
+ describe ".save" do
645
+
646
+ before do
647
+ Person.create(ssn: "432-97-1113")
648
+ end
649
+
650
+ context "when a mongodb error occurs" do
651
+
652
+ let(:person) do
653
+ Person.new(ssn: "432-97-1113")
654
+ end
655
+
656
+ before do
657
+ Person.create_indexes
658
+ end
659
+
660
+ it "bubbles up to the caller" do
661
+ expect {
662
+ person.save
663
+ }.to raise_error(Mongo::Error::OperationFailure)
664
+ end
665
+ end
666
+ end
667
+
668
+ describe ".save!" do
669
+
670
+ before do
671
+ Person.create!(ssn: "432-97-1114")
672
+ end
673
+
674
+ context "when a mongodb error occurs" do
675
+
676
+ let(:person) do
677
+ Person.new(ssn: "432-97-1114")
678
+ end
679
+
680
+ before do
681
+ Person.create_indexes
682
+ end
683
+
684
+ it "bubbles up to the caller" do
685
+ expect {
686
+ person.save!
687
+ }.to raise_error(Mongo::Error::OperationFailure)
688
+ end
689
+ end
690
+
691
+ context "when a validation error occurs" do
692
+
693
+ let(:account) do
694
+ Account.new(name: "this name is way too long")
695
+ end
696
+
697
+ it "raises the validation error" do
698
+ expect {
699
+ account.save!
700
+ }.to raise_error(Mongoid::Errors::Validations)
701
+ end
702
+ end
703
+ end
704
+ end
705
+ end
706
+
707
+ context "when overriding the default database", if: non_legacy_server? do
708
+
709
+ let(:file) do
710
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
711
+ end
712
+
713
+ before do
714
+ Mongoid::Config.load!(file, :test)
715
+ end
716
+
717
+ context "when the override is global" do
718
+
719
+ before do
720
+ Mongoid.override_database(:mongoid_optional)
721
+ end
722
+
723
+ after do
724
+ Band.delete_all
725
+ Mongoid.override_database(nil)
726
+ end
727
+
728
+ let!(:band) do
729
+ Band.create(name: "Tool")
730
+ end
731
+
732
+ it "persists to the overridden database" do
733
+ Band.mongo_client.with(database: :mongoid_optional) do |sess|
734
+ expect(sess[:bands].find(name: "Tool")).to_not be_nil
735
+ end
736
+ end
737
+ end
738
+ end
739
+ end