mongoid 7.1.0 → 7.1.1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +6 -6
  5. data/README.md +1 -1
  6. data/lib/config/locales/en.yml +4 -4
  7. data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
  8. data/lib/mongoid/association/referenced/eager.rb +29 -9
  9. data/lib/mongoid/config.rb +39 -9
  10. data/lib/mongoid/criteria.rb +16 -3
  11. data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
  12. data/lib/mongoid/criteria/queryable/selectable.rb +94 -7
  13. data/lib/mongoid/criteria/queryable/storable.rb +104 -99
  14. data/lib/mongoid/errors/eager_load.rb +2 -0
  15. data/lib/mongoid/persistable/pushable.rb +7 -1
  16. data/lib/mongoid/serializable.rb +9 -3
  17. data/lib/mongoid/version.rb +1 -1
  18. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
  19. data/spec/app/models/coding.rb +4 -0
  20. data/spec/app/models/coding/pull_request.rb +12 -0
  21. data/spec/app/models/delegating_patient.rb +16 -0
  22. data/spec/app/models/publication.rb +5 -0
  23. data/spec/app/models/publication/encyclopedia.rb +12 -0
  24. data/spec/app/models/publication/review.rb +14 -0
  25. data/spec/integration/document_spec.rb +22 -0
  26. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
  27. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +504 -127
  28. data/spec/mongoid/criteria/queryable/selectable_spec.rb +52 -0
  29. data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
  30. data/spec/mongoid/criteria_spec.rb +32 -0
  31. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  32. data/spec/mongoid/serializable_spec.rb +129 -18
  33. data/spec/spec_helper.rb +2 -0
  34. data/spec/support/expectations.rb +3 -1
  35. data/spec/support/helpers.rb +11 -0
  36. metadata +504 -490
  37. metadata.gz.sig +0 -0
@@ -6,6 +6,8 @@ module Mongoid
6
6
 
7
7
  # This error is raised when attempting to eager load a many to many
8
8
  # association.
9
+ #
10
+ # @deprecated No longer used by Mongoid per MONGOID-4841.
9
11
  class EagerLoad < MongoidError
10
12
 
11
13
  # Create the new eager load error.
@@ -24,7 +24,13 @@ module Mongoid
24
24
  def add_to_set(adds)
25
25
  prepare_atomic_operation do |ops|
26
26
  process_atomic_operations(adds) do |field, value|
27
- existing = send(field) || (attributes[field] ||= [])
27
+ existing = send(field) || attributes[field]
28
+ if existing.nil?
29
+ attributes[field] = []
30
+ # Read the value out of attributes:
31
+ # https://jira.mongodb.org/browse/MONGOID-4874
32
+ existing = attributes[field]
33
+ end
28
34
  values = [ value ].flatten(1)
29
35
  values.each do |val|
30
36
  existing.push(val) unless existing.include?(val)
@@ -13,10 +13,16 @@ module Mongoid
13
13
  # We need to redefine where the JSON configuration is getting defined,
14
14
  # similar to +ActiveRecord+.
15
15
  included do
16
- extend Forwardable
17
16
 
18
- undef_method :include_root_in_json
19
- def_delegator ::Mongoid, :include_root_in_json
17
+ class << self
18
+ # Note that this intentionally only delegates :include_root_in_json
19
+ # and not :include_root_in_json? - delegating the latter produces
20
+ # wrong behavior.
21
+ # Also note that this intentionally uses the ActiveSupport delegation
22
+ # functionality and not the Ruby standard library one.
23
+ # See https://jira.mongodb.org/browse/MONGOID-4849.
24
+ delegate :include_root_in_json, to: ::Mongoid
25
+ end
20
26
  end
21
27
 
22
28
  # Gets the document as a serializable hash, used by ActiveModel's JSON
@@ -2,5 +2,5 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  module Mongoid
5
- VERSION = "7.1.0"
5
+ VERSION = "7.1.1"
6
6
  end
@@ -114,12 +114,37 @@ development:
114
114
 
115
115
  # Configure Mongoid specific options. (optional)
116
116
  options:
117
- # Includes the root model name in json serialization. (default: false)
117
+ # Application name that is printed to the mongodb logs upon establishing
118
+ # a connection in server versions >= 3.4. Note that the name cannot
119
+ # exceed 128 bytes. It is also used as the database name if the
120
+ # database name is not explicitly defined. (default: nil)
121
+ # app_name: MyApplicationName
122
+
123
+ # Create indexes in background by default. (default: false)
124
+ # background_indexing: false
125
+
126
+ # Mark belongs_to associations as required by default, so that saving a
127
+ # model with a missing belongs_to association will trigger a validation
128
+ # error. (default: true)
129
+ # belongs_to_required_by_default: true
130
+
131
+ # Raise an exception when a field is redefined. (default: false)
132
+ # duplicate_fields_exception: false
133
+
134
+ # Include the root model name in json serialization. (default: false)
118
135
  # include_root_in_json: false
119
136
 
120
137
  # Include the _type field in serialization. (default: false)
121
138
  # include_type_for_serialization: false
122
139
 
140
+ # Whether to join nested persistence contexts for atomic operations
141
+ # to parent contexts by default. (default: false)
142
+ # join_contexts: false
143
+
144
+ # Set the Mongoid and Ruby driver log levels when Mongoid is not using
145
+ # Ruby on Rails logger instance. (default: :info)
146
+ # log_level: :info
147
+
123
148
  # Preload all models in development, needed when models use
124
149
  # inheritance. (default: false)
125
150
  # preload_models: false
@@ -132,32 +157,16 @@ development:
132
157
  # existing method. (default: false)
133
158
  # scope_overwrite_exception: false
134
159
 
135
- # Raise an error when defining a field with the same name as an
136
- # existing method. (default: false)
137
- # duplicate_fields_exception: false
138
-
139
- # Use Active Support's time zone in conversions. (default: true)
160
+ # Use ActiveSupport's time zone in time operations instead of
161
+ # the Ruby default time zone. See the time zone section below for
162
+ # further information. (default: true)
140
163
  # use_activesupport_time_zone: true
141
164
 
142
- # Ensure all times are UTC in the app side. (default: false)
165
+ # Return stored times as UTC. See the time zone section below for
166
+ # further information. Most applications should not use this option.
167
+ # (default: false)
143
168
  # use_utc: false
144
169
 
145
- # Set the Mongoid and Ruby driver log levels when not in a Rails
146
- # environment. The Mongoid logger will be set to the Rails logger
147
- # otherwise.(default: :info)
148
- # log_level: :info
149
-
150
- # Control whether `belongs_to` association is required. By default
151
- # `belongs_to` will trigger a validation error if the association
152
- # is not present. (default: true)
153
- # belongs_to_required_by_default: true
154
-
155
- # Application name that is printed to the mongodb logs upon establishing a
156
- # connection in server versions >= 3.4. Note that the name cannot exceed 128 bytes.
157
- # app_name: MyApplicationName
158
-
159
- # Use background indexes by default if `background` option not specified. (default: false)
160
- # background_indexing: false
161
170
  test:
162
171
  clients:
163
172
  default:
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'app/models/coding/pull_request'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Coding
5
+ class PullRequest
6
+ include Mongoid::Document
7
+
8
+ field :title, type: String
9
+
10
+ has_many :reviews, class_name: 'Publication::Review', as: :reviewable
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ class DelegatingPatient
5
+ include Mongoid::Document
6
+
7
+ embeds_one :email
8
+
9
+ # Instance level delegation
10
+ delegate :address, to: :email
11
+
12
+ class << self
13
+ # Class level delegation
14
+ delegate :default_client, to: ::Mongoid
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'app/models/publication/encyclopedia'
5
+ require 'app/models/publication/review'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Publication
5
+ class Encyclopedia
6
+ include Mongoid::Document
7
+
8
+ field :title, type: String
9
+
10
+ has_many :reviews, class_name: 'Publication::Review', as: :reviewable
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Publication
5
+ class Review
6
+ include Mongoid::Document
7
+
8
+ field :summary
9
+
10
+ belongs_to :reviewable, polymorphic: true
11
+ belongs_to :reviewer, polymorphic: true
12
+ belongs_to :template
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Mongoid::Document do
7
+ context 'when including class uses delegate' do
8
+ let(:patient) do
9
+ DelegatingPatient.new(
10
+ email: Email.new(address: 'test@example.com'),
11
+ )
12
+ end
13
+
14
+ it 'works for instance level delegation' do
15
+ patient.address.should == 'test@example.com'
16
+ end
17
+
18
+ it 'works for class level delegation' do
19
+ DelegatingPatient.default_client.should be Mongoid.default_client
20
+ end
21
+ end
22
+ end
@@ -114,13 +114,13 @@ describe Mongoid::Association::Referenced::BelongsTo::Eager do
114
114
  end
115
115
 
116
116
  it "does not query when touching the association" do
117
- expect_query(0) do
117
+ expect_no_queries do
118
118
  expect(eager.person).to eq(person)
119
119
  end
120
120
  end
121
121
 
122
122
  it "does not query when updating the association" do
123
- expect_query(0) do
123
+ expect_no_queries do
124
124
  eager.person.username = "arthurnn"
125
125
  end
126
126
  end
@@ -146,18 +146,201 @@ describe Mongoid::Association::Referenced::BelongsTo::Eager do
146
146
 
147
147
  context "when the association is polymorphic" do
148
148
 
149
- let!(:movie) do
150
- Movie.create(name: "Bladerunner")
149
+ context "without namespaces" do
150
+
151
+ let!(:stand_alone_rating) do
152
+ Rating.create(value: 7)
153
+ end
154
+
155
+ let!(:bar) do
156
+ Bar.create(name: "FooBar")
157
+ end
158
+
159
+ let(:bar_rating) do
160
+ bar.create_rating(value: 5)
161
+ end
162
+
163
+ let!(:movie) do
164
+ Movie.create(name: "Bladerunner")
165
+ end
166
+
167
+ let(:movie_rating) do
168
+ movie.ratings.create(value: 10)
169
+ end
170
+
171
+ let(:eager) do
172
+ Rating.includes(:ratable).entries
173
+ end
174
+
175
+ context "when the eager load has returned documents" do
176
+
177
+ before do
178
+ bar_rating
179
+ movie_rating
180
+ eager
181
+ end
182
+
183
+ it "puts the documents in the parent document" do
184
+ expect(eager.map { |e| e.ivar(:ratable) }).to eq([nil, bar, movie])
185
+ end
186
+
187
+ it "does not query when touching the association" do
188
+ expect_no_queries do
189
+ expect(eager.map(&:ratable)).to eq([nil, bar, movie])
190
+ end
191
+ end
192
+
193
+ it "does not query when updating the association" do
194
+ expect_no_queries do
195
+ eager.last.ratable.name = "Easy rider"
196
+ end
197
+ end
198
+ end
199
+
200
+ context "when the eager load has not returned documents" do
201
+
202
+ before { eager }
203
+
204
+ it "does not set anything on the parent" do
205
+ expect(eager.map { |e| e.ivar(:ratable) }).to all(be nil)
206
+ end
207
+
208
+ it "has a nil association" do
209
+ expect(eager.map(&:ratable)).to all(be nil)
210
+ end
211
+ end
212
+ end
213
+
214
+ context "with namespaces" do
215
+
216
+ let!(:stand_alone_review) do
217
+ Publication::Review.create(summary: "awful")
218
+ end
219
+
220
+ let!(:encyclopedia) do
221
+ Publication::Encyclopedia.create(title: "Encyclopedia Britannica")
222
+ end
223
+
224
+ let(:encyclopedia_review) do
225
+ encyclopedia.reviews.create(summary: "inspiring")
226
+ end
227
+
228
+ let!(:pull_request) do
229
+ Coding::PullRequest.create(title: "Add eager loading for polymorphic belongs_to associations")
230
+ end
231
+
232
+ let(:pull_request_review) do
233
+ pull_request.reviews.create(summary: "Looks good to me")
234
+ end
235
+
236
+ let(:eager) do
237
+ Publication::Review.includes(:reviewable).entries
238
+ end
239
+
240
+ context "when the eager load has returned documents" do
241
+
242
+ before do
243
+ encyclopedia_review
244
+ pull_request_review
245
+ eager
246
+ end
247
+
248
+ it "puts the documents in the parent document" do
249
+ expect(eager.map { |e| e.ivar(:reviewable) }).to eq([nil, encyclopedia, pull_request])
250
+ end
251
+
252
+ it "does not query when touching the association" do
253
+ expect_no_queries do
254
+ expect(eager.map(&:reviewable)).to eq([nil, encyclopedia, pull_request])
255
+ end
256
+ end
257
+
258
+ it "does not query when updating the association" do
259
+ expect_no_queries do
260
+ eager.last.reviewable.title = "Load stuff eagerly"
261
+ end
262
+ end
263
+ end
264
+
265
+ context "when the eager load has not returned documents" do
266
+
267
+ before { eager }
268
+
269
+ it "does not set anything on the parent" do
270
+ expect(eager.map { |e| e.ivar(:reviewable) }).to all(be nil)
271
+ end
272
+
273
+ it "has a nil association" do
274
+ expect(eager.map(&:reviewable)).to all(be nil)
275
+ end
276
+ end
151
277
  end
152
278
 
153
- let!(:rating) do
154
- movie.ratings.create(value: 10)
279
+ context 'when eager loading multiple associations' do
280
+ let(:reviewable) do
281
+ Publication::Encyclopedia.create!(title: "Encyclopedia Britannica")
282
+ end
283
+
284
+ let!(:reviewable_review) do
285
+ Publication::Review.create!(summary: "awful",
286
+ reviewable: reviewable)
287
+ end
288
+
289
+ let(:reviewer) do
290
+ Dog.create!
291
+ end
292
+
293
+ let!(:reviewer_review) do
294
+ Publication::Review.create(summary: "okay",
295
+ reviewer: reviewer)
296
+ end
297
+
298
+ let(:template) do
299
+ Template.create!
300
+ end
301
+
302
+ let!(:template_review) do
303
+ Publication::Review.create(summary: "Looks good to me",
304
+ template: template)
305
+ end
306
+
307
+ let(:eager) do
308
+ Publication::Review.includes(:reviewable, :reviewer, :template).entries
309
+ end
310
+
311
+ it 'loads all associations eagerly' do
312
+ loaded = expect_query(4) do
313
+ eager
314
+ end
315
+
316
+ expect_no_queries do
317
+ eager.map(&:reviewable).compact.should == [reviewable]
318
+ end
319
+
320
+ expect_no_queries do
321
+ eager.map(&:reviewer).compact.should == [reviewer]
322
+ end
323
+
324
+ expect_no_queries do
325
+ eager.map(&:template).compact.should == [template]
326
+ end
327
+ end
155
328
  end
156
329
 
157
- it "raises an error" do
158
- expect {
159
- Rating.includes(:ratable).last
160
- }.to raise_error(Mongoid::Errors::EagerLoad)
330
+ context 'when eager loading an association that has type but not value set' do
331
+
332
+ let!(:reviewer_review) do
333
+ Publication::Review.create(summary: "okay",
334
+ reviewer_type: 'Dog')
335
+ end
336
+
337
+ let(:eager) do
338
+ Publication::Review.includes(:reviewable, :reviewer, :template).entries
339
+ end
340
+
341
+ it 'does not error' do
342
+ eager.map(&:reviewer).should == [nil]
343
+ end
161
344
  end
162
345
  end
163
346