mongoid 4.0.0.alpha2 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +13 -0
  5. data/lib/mongoid.rb +3 -1
  6. data/lib/mongoid/atomic.rb +1 -1
  7. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  8. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  9. data/lib/mongoid/attributes.rb +23 -1
  10. data/lib/mongoid/attributes/processing.rb +1 -1
  11. data/lib/mongoid/composable.rb +3 -2
  12. data/lib/mongoid/contextual/command.rb +0 -26
  13. data/lib/mongoid/contextual/geo_near.rb +1 -1
  14. data/lib/mongoid/contextual/mongo.rb +6 -29
  15. data/lib/mongoid/contextual/text_search.rb +3 -5
  16. data/lib/mongoid/criteria.rb +1 -1
  17. data/lib/mongoid/criteria/modifiable.rb +27 -7
  18. data/lib/mongoid/criteria/permission.rb +70 -0
  19. data/lib/mongoid/document.rb +5 -6
  20. data/lib/mongoid/errors.rb +2 -0
  21. data/lib/mongoid/errors/document_not_destroyed.rb +25 -0
  22. data/lib/mongoid/errors/readonly_document.rb +24 -0
  23. data/lib/mongoid/extensions/boolean.rb +1 -0
  24. data/lib/mongoid/extensions/hash.rb +1 -1
  25. data/lib/mongoid/factory.rb +5 -3
  26. data/lib/mongoid/fields.rb +32 -0
  27. data/lib/mongoid/fields/localized.rb +1 -1
  28. data/lib/mongoid/fields/standard.rb +1 -1
  29. data/lib/mongoid/findable.rb +1 -0
  30. data/lib/mongoid/interceptable.rb +11 -6
  31. data/lib/mongoid/log_subscriber.rb +34 -1
  32. data/lib/mongoid/persistable/deletable.rb +1 -0
  33. data/lib/mongoid/persistable/destroyable.rb +7 -2
  34. data/lib/mongoid/persistable/updatable.rb +27 -26
  35. data/lib/mongoid/query_cache.rb +246 -0
  36. data/lib/mongoid/railties/database.rake +4 -26
  37. data/lib/mongoid/relations.rb +8 -22
  38. data/lib/mongoid/relations/accessors.rb +0 -3
  39. data/lib/mongoid/relations/binding.rb +1 -1
  40. data/lib/mongoid/relations/bindings/embedded/in.rb +1 -1
  41. data/lib/mongoid/relations/eager.rb +5 -6
  42. data/lib/mongoid/relations/eager/base.rb +97 -5
  43. data/lib/mongoid/relations/eager/belongs_to.rb +1 -0
  44. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +16 -9
  45. data/lib/mongoid/relations/eager/has_many.rb +1 -0
  46. data/lib/mongoid/relations/eager/has_one.rb +1 -0
  47. data/lib/mongoid/relations/embedded/batchable.rb +1 -1
  48. data/lib/mongoid/relations/embedded/in.rb +4 -4
  49. data/lib/mongoid/relations/embedded/many.rb +7 -5
  50. data/lib/mongoid/relations/embedded/one.rb +1 -1
  51. data/lib/mongoid/relations/macros.rb +1 -0
  52. data/lib/mongoid/relations/marshalable.rb +3 -3
  53. data/lib/mongoid/relations/proxy.rb +12 -10
  54. data/lib/mongoid/relations/referenced/in.rb +2 -2
  55. data/lib/mongoid/relations/referenced/many.rb +9 -9
  56. data/lib/mongoid/relations/referenced/many_to_many.rb +7 -7
  57. data/lib/mongoid/relations/referenced/one.rb +4 -4
  58. data/lib/mongoid/{state.rb → stateful.rb} +13 -1
  59. data/lib/mongoid/tasks/database.rake +31 -0
  60. data/lib/mongoid/tasks/database.rb +107 -0
  61. data/lib/mongoid/threaded.rb +0 -47
  62. data/lib/mongoid/validatable/uniqueness.rb +4 -16
  63. data/lib/mongoid/version.rb +1 -1
  64. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +0 -3
  65. data/lib/rails/mongoid.rb +0 -124
  66. data/spec/app/models/edit.rb +5 -0
  67. data/spec/app/models/even.rb +7 -0
  68. data/spec/app/models/line_item.rb +1 -1
  69. data/spec/app/models/note.rb +2 -0
  70. data/spec/app/models/odd.rb +7 -0
  71. data/spec/app/models/record.rb +5 -0
  72. data/spec/app/models/wiki_page.rb +1 -1
  73. data/spec/mongoid/attributes_spec.rb +76 -1
  74. data/spec/mongoid/changeable_spec.rb +6 -2
  75. data/spec/mongoid/contextual/mongo_spec.rb +3 -1
  76. data/spec/mongoid/contextual/text_search_spec.rb +3 -1
  77. data/spec/mongoid/criteria/modifiable_spec.rb +192 -0
  78. data/spec/mongoid/criteria_spec.rb +6 -2
  79. data/spec/mongoid/errors/document_not_destroyed_spec.rb +33 -0
  80. data/spec/mongoid/errors/readonly_document_spec.rb +29 -0
  81. data/spec/mongoid/fields/localized_spec.rb +15 -0
  82. data/spec/mongoid/fields_spec.rb +88 -2
  83. data/spec/mongoid/log_subscriber_spec.rb +3 -3
  84. data/spec/mongoid/persistable/deletable_spec.rb +14 -1
  85. data/spec/mongoid/persistable/destroyable_spec.rb +45 -1
  86. data/spec/mongoid/persistable/savable_spec.rb +34 -5
  87. data/spec/mongoid/query_cache_spec.rb +197 -0
  88. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +2 -2
  89. data/spec/mongoid/relations/builders/referenced/many_spec.rb +1 -1
  90. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +11 -37
  91. data/spec/mongoid/relations/eager/has_one_spec.rb +1 -1
  92. data/spec/mongoid/relations/embedded/in_spec.rb +1 -1
  93. data/spec/mongoid/relations/embedded/many_spec.rb +10 -10
  94. data/spec/mongoid/relations/embedded/one_spec.rb +10 -2
  95. data/spec/mongoid/relations/referenced/in_spec.rb +1 -1
  96. data/spec/mongoid/relations/referenced/many_spec.rb +37 -2
  97. data/spec/mongoid/relations/touchable_spec.rb +20 -0
  98. data/spec/mongoid/{state_spec.rb → stateful_spec.rb} +26 -1
  99. data/spec/mongoid/tasks/database_rake_spec.rb +285 -0
  100. data/spec/mongoid/tasks/database_spec.rb +148 -0
  101. data/spec/mongoid/validatable/uniqueness_spec.rb +7 -0
  102. data/spec/rails/mongoid_spec.rb +0 -316
  103. data/spec/spec_helper.rb +1 -0
  104. metadata +30 -8
@@ -178,6 +178,21 @@ describe Mongoid::Fields::Localized do
178
178
  end
179
179
  end
180
180
 
181
+ context "when no type is provided" do
182
+
183
+ let(:field) do
184
+ described_class.new(:description, localize: true)
185
+ end
186
+
187
+ let(:value) do
188
+ field.demongoize({ "en" => false })
189
+ end
190
+
191
+ it "allows booleans to be returned" do
192
+ expect(value).to eq(false)
193
+ end
194
+ end
195
+
181
196
  context "when the type is not a string" do
182
197
 
183
198
  let(:field) do
@@ -309,6 +309,92 @@ describe Mongoid::Fields do
309
309
  end
310
310
  end
311
311
 
312
+ context "when providing a root Boolean type" do
313
+
314
+ let(:klass) do
315
+ Class.new do
316
+ include Mongoid::Document
317
+ end
318
+ end
319
+
320
+ it "converts to Mongoid::Boolean" do
321
+ expect(klass.field(:test, type: Boolean).type).to be(Mongoid::Boolean)
322
+ end
323
+ end
324
+
325
+ context "when using symbol types" do
326
+
327
+ let(:klass) do
328
+ Class.new do
329
+ include Mongoid::Document
330
+ end
331
+ end
332
+
333
+ it "converts :array to Array" do
334
+ expect(klass.field(:test, type: :array).type).to be(Array)
335
+ end
336
+
337
+ it "converts :big_decimal to BigDecimal" do
338
+ expect(klass.field(:test, type: :big_decimal).type).to be(BigDecimal)
339
+ end
340
+
341
+ it "converts :binary to BSON::Binary" do
342
+ expect(klass.field(:test, type: :binary).type).to be(BSON::Binary)
343
+ end
344
+
345
+ it "converts :boolean to Mongoid::Boolean" do
346
+ expect(klass.field(:test, type: :boolean).type).to be(Mongoid::Boolean)
347
+ end
348
+
349
+ it "converts :date to Date" do
350
+ expect(klass.field(:test, type: :date).type).to be(Date)
351
+ end
352
+
353
+ it "converts :date_time to DateTime" do
354
+ expect(klass.field(:test, type: :date_time).type).to be(DateTime)
355
+ end
356
+
357
+ it "converts :float to Float" do
358
+ expect(klass.field(:test, type: :float).type).to be(Float)
359
+ end
360
+
361
+ it "converts :hash to Hash" do
362
+ expect(klass.field(:test, type: :hash).type).to be(Hash)
363
+ end
364
+
365
+ it "converts :integer to Integer" do
366
+ expect(klass.field(:test, type: :integer).type).to be(Integer)
367
+ end
368
+
369
+ it "converts :object_id to BSON::ObjectId" do
370
+ expect(klass.field(:test, type: :object_id).type).to be(BSON::ObjectId)
371
+ end
372
+
373
+ it "converts :range to Range" do
374
+ expect(klass.field(:test, type: :range).type).to be(Range)
375
+ end
376
+
377
+ it "converts :regexp to Rexegp" do
378
+ expect(klass.field(:test, type: :regexp).type).to be(Regexp)
379
+ end
380
+
381
+ it "converts :set to Set" do
382
+ expect(klass.field(:test, type: :set).type).to be(Set)
383
+ end
384
+
385
+ it "converts :string to String" do
386
+ expect(klass.field(:test, type: :string).type).to be(String)
387
+ end
388
+
389
+ it "converts :symbol to Symbol" do
390
+ expect(klass.field(:test, type: :symbol).type).to be(Symbol)
391
+ end
392
+
393
+ it "converts :time to Time" do
394
+ expect(klass.field(:test, type: :time).type).to be(Time)
395
+ end
396
+ end
397
+
312
398
  context "when the options are valid" do
313
399
 
314
400
  context "when the options are all standard" do
@@ -729,11 +815,11 @@ describe Mongoid::Fields do
729
815
 
730
816
  context "when the field name conflicts with mongoid's internals" do
731
817
 
732
- context "when the field is named metadata" do
818
+ context "when the field is named __metadata" do
733
819
 
734
820
  it "raises an error" do
735
821
  expect {
736
- Person.field(:metadata)
822
+ Person.field(:__metadata)
737
823
  }.to raise_error(Mongoid::Errors::InvalidField)
738
824
  end
739
825
  end
@@ -54,15 +54,15 @@ describe Mongoid::LogSubscriber do
54
54
  TestLogSubscriber.log_subscribers.pop
55
55
  end
56
56
 
57
- it "pushes 2 log subscribers" do
58
- expect(Mongoid::LogSubscriber.subscribers.size).to eq(2)
57
+ it "pushes the new log subscriber" do
58
+ expect(Mongoid::LogSubscriber.subscribers.last).to be_a TestLogSubscriber
59
59
  end
60
60
 
61
61
  context "when quering the database" do
62
62
 
63
63
  before do
64
64
  expect(subscribe).to receive(:debug).once
65
- Band.all.to_a
65
+ PetOwner.all.to_a
66
66
  end
67
67
 
68
68
  it "sends operations logs to TestLogSubscriber" do
@@ -4,10 +4,23 @@ describe Mongoid::Persistable::Deletable do
4
4
 
5
5
  describe "#delete" do
6
6
 
7
- let(:person) do
7
+ let!(:person) do
8
8
  Person.create
9
9
  end
10
10
 
11
+ context "when deleting a readonly document" do
12
+
13
+ let(:from_db) do
14
+ Person.only(:_id).first
15
+ end
16
+
17
+ it "raises an error" do
18
+ expect {
19
+ from_db.delete
20
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
21
+ end
22
+ end
23
+
11
24
  context "when removing a root document" do
12
25
 
13
26
  let!(:deleted) do
@@ -4,10 +4,23 @@ describe Mongoid::Persistable::Destroyable do
4
4
 
5
5
  describe "#destroy" do
6
6
 
7
- let(:person) do
7
+ let!(:person) do
8
8
  Person.create
9
9
  end
10
10
 
11
+ context "when destroying a readonly document" do
12
+
13
+ let(:from_db) do
14
+ Person.only(:_id).first
15
+ end
16
+
17
+ it "raises an error" do
18
+ expect {
19
+ from_db.destroy
20
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
21
+ end
22
+ end
23
+
11
24
  context "when removing a root document" do
12
25
 
13
26
  let!(:destroyd) do
@@ -102,6 +115,37 @@ describe Mongoid::Persistable::Destroyable do
102
115
  end
103
116
  end
104
117
 
118
+ describe "#destroy!" do
119
+
120
+ context "when no validation callback returns false" do
121
+
122
+ let(:person) do
123
+ Person.create
124
+ end
125
+
126
+ it "returns true" do
127
+ expect(person.destroy!).to eq(true)
128
+ end
129
+ end
130
+
131
+ context "when a validation callback returns false" do
132
+
133
+ let(:album) do
134
+ Album.create
135
+ end
136
+
137
+ before do
138
+ expect(album).to receive(:set_parent_name).and_return(false)
139
+ end
140
+
141
+ it "raises an exception" do
142
+ expect {
143
+ album.destroy!
144
+ }.to raise_error(Mongoid::Errors::DocumentNotDestroyed)
145
+ end
146
+ end
147
+ end
148
+
105
149
  describe "#destroy_all" do
106
150
 
107
151
  let!(:person) do
@@ -94,11 +94,6 @@ describe Mongoid::Persistable::Savable do
94
94
  it "does not flag the excluded fields as dirty" do
95
95
  expect(limited.changes).to be_empty
96
96
  end
97
-
98
- it "does not overwrite with the default" do
99
- limited.save
100
- expect(limited.reload.age).to eq(20)
101
- end
102
97
  end
103
98
 
104
99
  context "when iterating over the documents" do
@@ -273,6 +268,23 @@ describe Mongoid::Persistable::Savable do
273
268
  end
274
269
  end
275
270
  end
271
+
272
+ context "when the document is readonly" do
273
+
274
+ let(:person) do
275
+ Person.only(:title).first
276
+ end
277
+
278
+ before do
279
+ Person.create(title: "sir")
280
+ end
281
+
282
+ it "raises an error" do
283
+ expect {
284
+ person.save
285
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
286
+ end
287
+ end
276
288
  end
277
289
 
278
290
  describe "save!" do
@@ -428,5 +440,22 @@ describe Mongoid::Persistable::Savable do
428
440
  expect(from_db.shapes.first.canvas).to eq(firefox)
429
441
  end
430
442
  end
443
+
444
+ context "when the document is readonly" do
445
+
446
+ let(:person) do
447
+ Person.only(:title).first
448
+ end
449
+
450
+ before do
451
+ Person.create(title: "sir")
452
+ end
453
+
454
+ it "raises an error" do
455
+ expect {
456
+ person.save!
457
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
458
+ end
459
+ end
431
460
  end
432
461
  end
@@ -0,0 +1,197 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::QueryCache do
4
+
5
+ around do |spec|
6
+ Mongoid::QueryCache.clear_cache
7
+ Mongoid::QueryCache.cache { spec.run }
8
+ end
9
+
10
+ context "when querying for a single document" do
11
+
12
+ [ :first, :one ].each do |method|
13
+
14
+ before do
15
+ Band.all.send(method)
16
+ end
17
+
18
+ context "when query cache disable" do
19
+
20
+ before do
21
+ Mongoid::QueryCache.enabled = false
22
+ end
23
+
24
+ it "queries again" do
25
+ expect_query(1) do
26
+ Band.all.send(method)
27
+ end
28
+ end
29
+ end
30
+
31
+ context "with same selector" do
32
+
33
+ it "does not query again" do
34
+ expect_no_queries do
35
+ Band.all.send(method)
36
+ end
37
+ end
38
+ end
39
+
40
+ context "with different selector" do
41
+
42
+ it "queries again" do
43
+ expect_query(1) do
44
+ Band.where(id: 1).send(method)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ context "when querying in the same collection" do
52
+
53
+ before do
54
+ Band.all.to_a
55
+ end
56
+
57
+ context "when query cache disable" do
58
+
59
+ before do
60
+ Mongoid::QueryCache.enabled = false
61
+ end
62
+
63
+ it "queries again" do
64
+ expect_query(1) do
65
+ Band.all.to_a
66
+ end
67
+ end
68
+ end
69
+
70
+ context "with same selector" do
71
+
72
+ it "does not query again" do
73
+ expect_no_queries do
74
+ Band.all.to_a
75
+ end
76
+ end
77
+ end
78
+
79
+ context "with different selector" do
80
+
81
+ it "queries again" do
82
+ expect_query(1) do
83
+ Band.where(id: 1).to_a
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ context "when querying in different collection" do
90
+
91
+ before do
92
+ Person.all.to_a
93
+ end
94
+
95
+ it "queries again" do
96
+ expect_query(1) do
97
+ Band.all.to_a
98
+ end
99
+ end
100
+ end
101
+
102
+ context "when inserting a new document" do
103
+
104
+ before do
105
+ Band.all.to_a
106
+ Band.create!
107
+ end
108
+
109
+ it "queries again" do
110
+ expect_query(1) do
111
+ Band.all.to_a
112
+ end
113
+ end
114
+ end
115
+
116
+ context "when deleting all documents" do
117
+
118
+ before do
119
+ Band.create!
120
+ Band.all.to_a
121
+ Band.delete_all
122
+ end
123
+
124
+ it "queries again" do
125
+ expect_query(1) do
126
+ Band.all.to_a
127
+ end
128
+ end
129
+ end
130
+
131
+ context "when destroying all documents" do
132
+
133
+ before do
134
+ Band.create!
135
+ Band.all.to_a
136
+ Band.destroy_all
137
+ end
138
+
139
+ it "queries again" do
140
+ expect_query(1) do
141
+ Band.all.to_a
142
+ end
143
+ end
144
+ end
145
+
146
+ context "when inserting an index" do
147
+
148
+ it "does not cache the query" do
149
+ expect(Mongoid::QueryCache).to receive(:cache_table).never
150
+ Band.collection.indexes.create(name: 1)
151
+ end
152
+ end
153
+ end
154
+
155
+ describe Mongoid::QueryCache::Middleware do
156
+
157
+ let :middleware do
158
+ Mongoid::QueryCache::Middleware.new(app)
159
+ end
160
+
161
+ context "when not touching mongoid on the app" do
162
+
163
+ let(:app) do
164
+ ->(env) { @enabled = Mongoid::QueryCache.enabled?; [200, env, "app"] }
165
+ end
166
+
167
+ it "returns success" do
168
+ code, _ = middleware.call({})
169
+ expect(code).to eq(200)
170
+ end
171
+
172
+ it "enableds the query cache" do
173
+ middleware.call({})
174
+ expect(@enabled).to be true
175
+ end
176
+ end
177
+
178
+ context "when querying on the app" do
179
+
180
+ let(:app) do
181
+ ->(env) {
182
+ Band.all.to_a
183
+ [200, env, "app"]
184
+ }
185
+ end
186
+
187
+ it "returns success" do
188
+ code, _ = middleware.call({})
189
+ expect(code).to eq(200)
190
+ end
191
+
192
+ it "cleans the query cache after reponds" do
193
+ middleware.call({})
194
+ expect(Mongoid::QueryCache.cache_table).to be_empty
195
+ end
196
+ end
197
+ end