mongoid 7.1.0.rc0 → 7.1.5
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +6 -6
- data/LICENSE +1 -1
- data/README.md +5 -5
- data/Rakefile +14 -0
- data/lib/config/locales/en.yml +5 -5
- data/lib/mongoid.rb +3 -2
- data/lib/mongoid/association/accessors.rb +37 -2
- data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
- data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
- data/lib/mongoid/association/many.rb +3 -2
- data/lib/mongoid/association/proxy.rb +6 -4
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -1
- data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
- data/lib/mongoid/association/referenced/eager.rb +29 -9
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -22
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -2
- data/lib/mongoid/atomic.rb +13 -3
- data/lib/mongoid/attributes.rb +28 -20
- data/lib/mongoid/clients/factory.rb +2 -2
- data/lib/mongoid/clients/options.rb +8 -8
- data/lib/mongoid/clients/sessions.rb +20 -4
- data/lib/mongoid/clients/storage_options.rb +5 -5
- data/lib/mongoid/config.rb +42 -12
- data/lib/mongoid/config/options.rb +5 -2
- data/lib/mongoid/contextual.rb +5 -4
- data/lib/mongoid/contextual/geo_near.rb +3 -2
- data/lib/mongoid/contextual/map_reduce.rb +3 -2
- data/lib/mongoid/contextual/mongo.rb +2 -1
- data/lib/mongoid/criteria.rb +23 -4
- data/lib/mongoid/criteria/modifiable.rb +2 -1
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -6
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
- data/lib/mongoid/criteria/queryable/mergeable.rb +75 -8
- data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
- data/lib/mongoid/criteria/queryable/selectable.rb +120 -13
- data/lib/mongoid/criteria/queryable/storable.rb +104 -99
- data/lib/mongoid/errors/eager_load.rb +2 -0
- data/lib/mongoid/errors/no_client_config.rb +2 -2
- data/lib/mongoid/errors/no_default_client.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +4 -2
- data/lib/mongoid/extensions/regexp.rb +1 -1
- data/lib/mongoid/fields.rb +2 -1
- data/lib/mongoid/fields/standard.rb +2 -1
- data/lib/mongoid/fields/validators/macro.rb +4 -1
- data/lib/mongoid/findable.rb +5 -4
- data/lib/mongoid/interceptable.rb +5 -1
- data/lib/mongoid/matchable/regexp.rb +2 -2
- data/lib/mongoid/persistable/pushable.rb +11 -2
- data/lib/mongoid/persistence_context.rb +6 -6
- data/lib/mongoid/query_cache.rb +61 -18
- data/lib/mongoid/railties/database.rake +7 -0
- data/lib/mongoid/serializable.rb +10 -2
- data/lib/mongoid/shardable.rb +56 -4
- data/lib/mongoid/tasks/database.rake +10 -5
- data/lib/mongoid/tasks/database.rb +83 -0
- data/lib/mongoid/timestamps/timeless.rb +3 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
- data/spec/app/models/coding.rb +4 -0
- data/spec/app/models/coding/pull_request.rb +12 -0
- data/spec/app/models/delegating_patient.rb +16 -0
- data/spec/app/models/passport.rb +1 -0
- data/spec/app/models/phone.rb +1 -0
- data/spec/app/models/publication.rb +5 -0
- data/spec/app/models/publication/encyclopedia.rb +12 -0
- data/spec/app/models/publication/review.rb +14 -0
- data/spec/integration/app_spec.rb +254 -0
- data/spec/integration/associations/embedded_spec.rb +54 -0
- data/spec/integration/associations/has_many_spec.rb +34 -0
- data/spec/integration/associations/has_one_spec.rb +34 -0
- data/spec/integration/bson_regexp_raw_spec.rb +20 -0
- data/spec/integration/criteria/date_field_spec.rb +41 -0
- data/spec/integration/criteria/logical_spec.rb +13 -0
- data/spec/integration/document_spec.rb +22 -0
- data/spec/integration/shardable_spec.rb +149 -0
- data/spec/lite_spec_helper.rb +15 -4
- data/spec/mongoid/association/accessors_spec.rb +238 -63
- data/spec/mongoid/association/embedded/embeds_many_models.rb +19 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
- data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +146 -68
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
- data/spec/mongoid/attributes_spec.rb +19 -7
- data/spec/mongoid/changeable_spec.rb +23 -0
- data/spec/mongoid/clients/factory_spec.rb +8 -8
- data/spec/mongoid/clients/options_spec.rb +11 -11
- data/spec/mongoid/clients/sessions_spec.rb +8 -4
- data/spec/mongoid/clients/transactions_spec.rb +20 -8
- data/spec/mongoid/clients_spec.rb +2 -2
- data/spec/mongoid/contextual/atomic_spec.rb +22 -11
- data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
- data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
- data/spec/mongoid/contextual/mongo_spec.rb +76 -53
- data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +45 -12
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1051 -392
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +52 -0
- data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
- data/spec/mongoid/criteria_spec.rb +36 -2
- data/spec/mongoid/document_fields_spec.rb +29 -0
- data/spec/mongoid/document_persistence_context_spec.rb +33 -0
- data/spec/mongoid/errors/no_client_config_spec.rb +2 -2
- data/spec/mongoid/errors/no_client_database_spec.rb +3 -3
- data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -3
- data/spec/mongoid/fields_spec.rb +24 -1
- data/spec/mongoid/indexable_spec.rb +6 -4
- data/spec/mongoid/interceptable_spec.rb +62 -0
- data/spec/mongoid/interceptable_spec_models.rb +76 -0
- data/spec/mongoid/matchable/default_spec.rb +1 -1
- data/spec/mongoid/matchable/regexp_spec.rb +2 -2
- data/spec/mongoid/matchable_spec.rb +2 -2
- data/spec/mongoid/persistable/pushable_spec.rb +55 -1
- data/spec/mongoid/query_cache_spec.rb +77 -9
- data/spec/mongoid/relations/proxy_spec.rb +1 -1
- data/spec/mongoid/scopable_spec.rb +2 -1
- data/spec/mongoid/serializable_spec.rb +129 -18
- data/spec/mongoid/shardable_models.rb +61 -0
- data/spec/mongoid/shardable_spec.rb +69 -16
- data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
- data/spec/mongoid/tasks/database_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -31
- data/spec/support/child_process_helper.rb +76 -0
- data/spec/support/cluster_config.rb +3 -3
- data/spec/support/constraints.rb +26 -10
- data/spec/support/expectations.rb +3 -1
- data/spec/support/helpers.rb +11 -0
- data/spec/support/lite_constraints.rb +22 -0
- data/spec/support/session_registry.rb +50 -0
- data/spec/support/spec_config.rb +12 -4
- metadata +518 -480
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '06912d432d08b07e80bad71d5073cf2d5a4924f097cdefed959107c6cad245ef'
|
|
4
|
+
data.tar.gz: d6880896621095c3d3017207d9966f99c17f7aea9a1d7366746e287e4c2cea04
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b9a2bcc459c5ae8f2d7dd5585e7c0c39869f6a860067ae4ab36c5df64efb524ef688d5ab087e1a52a9d6ea3101df66213ad607c62df7499e5706bcce3f0974c
|
|
7
|
+
data.tar.gz: cafe608ad57c0b91593bd570024c74aa6ed203f14e6ebe61b026601ef7c64ab8bc28d944a42e73aa6c1b1aea1510f83e9a64f869bee15ce549db2ade75e56295
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data.tar.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -1848,18 +1848,18 @@ child elements.
|
|
|
1848
1848
|
set a child on a relation without the proper inverse_of definitions
|
|
1849
1849
|
due to Mongoid not being able to determine it.
|
|
1850
1850
|
|
|
1851
|
-
class
|
|
1851
|
+
class Car
|
|
1852
1852
|
include Mongoid::Document
|
|
1853
|
-
embeds_one :
|
|
1853
|
+
embeds_one :engine, class_name: "Motor"
|
|
1854
1854
|
end
|
|
1855
1855
|
|
|
1856
|
-
class
|
|
1856
|
+
class Motor
|
|
1857
1857
|
include Mongoid::Document
|
|
1858
|
-
embedded_in :
|
|
1858
|
+
embedded_in :machine, class_name: "Car"
|
|
1859
1859
|
end
|
|
1860
1860
|
|
|
1861
|
-
|
|
1862
|
-
|
|
1861
|
+
car = Car.new
|
|
1862
|
+
car.engine = Motor.new # raises an InverseNotFound error.
|
|
1863
1863
|
|
|
1864
1864
|
* \#1680 Polymorphic relations now use `*_type` keys in lookup queries.
|
|
1865
1865
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -17,9 +17,9 @@ Compatibility
|
|
|
17
17
|
|
|
18
18
|
Mongoid supports and is tested against:
|
|
19
19
|
|
|
20
|
-
- MRI 2.
|
|
21
|
-
- JRuby 9.
|
|
22
|
-
- MongoDB server 2.6-4.
|
|
20
|
+
- MRI 2.3-2.7
|
|
21
|
+
- JRuby 9.2
|
|
22
|
+
- MongoDB server 2.6-4.4
|
|
23
23
|
|
|
24
24
|
Issues
|
|
25
25
|
------
|
|
@@ -31,14 +31,14 @@ Support
|
|
|
31
31
|
-------
|
|
32
32
|
|
|
33
33
|
* [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoid)
|
|
34
|
-
* [
|
|
34
|
+
* [MongoDB Community Forum](https://developer.mongodb.com/community/forums/tags/c/drivers-odms-connectors/7/mongoid-odm)
|
|
35
35
|
* [#mongoid](http://webchat.freenode.net/?channels=mongoid) on Freenode IRC
|
|
36
36
|
|
|
37
37
|
License
|
|
38
38
|
-------
|
|
39
39
|
|
|
40
40
|
Copyright (c) 2009-2016 Durran Jordan
|
|
41
|
-
Copyright (c) 2015-
|
|
41
|
+
Copyright (c) 2015-2020 MongoDB, Inc.
|
|
42
42
|
|
|
43
43
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
44
44
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler"
|
|
4
|
+
require "bundler/gem_tasks"
|
|
4
5
|
Bundler.setup
|
|
5
6
|
|
|
6
7
|
require "rake"
|
|
@@ -9,6 +10,9 @@ require "rspec/core/rake_task"
|
|
|
9
10
|
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
|
10
11
|
require "mongoid/version"
|
|
11
12
|
|
|
13
|
+
tasks = Rake.application.instance_variable_get('@tasks')
|
|
14
|
+
tasks['release:do'] = tasks.delete('release')
|
|
15
|
+
|
|
12
16
|
task :gem => :build
|
|
13
17
|
task :build do
|
|
14
18
|
system "gem build mongoid.gemspec"
|
|
@@ -47,3 +51,13 @@ namespace :docs do
|
|
|
47
51
|
system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
|
|
48
52
|
end
|
|
49
53
|
end
|
|
54
|
+
|
|
55
|
+
namespace :release do
|
|
56
|
+
task :check_private_key do
|
|
57
|
+
unless File.exist?('gem-private_key.pem')
|
|
58
|
+
raise "No private key present, cannot release"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
task :release => ['release:check_private_key', 'release:do']
|
data/lib/config/locales/en.yml
CHANGED
|
@@ -249,7 +249,7 @@ en:
|
|
|
249
249
|
Example:\n
|
|
250
250
|
\_\_class Band\n
|
|
251
251
|
\_\_\_\_include Mongoid::Document\n
|
|
252
|
-
\_\_\_\_store_in collection: 'artists', database: '
|
|
252
|
+
\_\_\_\_store_in collection: 'artists', database: 'music'\n
|
|
253
253
|
\_\_end\n\n"
|
|
254
254
|
invalid_storage_parent:
|
|
255
255
|
message: "Invalid store_in call on class %{klass}."
|
|
@@ -282,13 +282,13 @@ en:
|
|
|
282
282
|
you will need to explicitly tell Mongoid on the association what
|
|
283
283
|
the inverse is.\n\n
|
|
284
284
|
Example:\n
|
|
285
|
-
\_\_class
|
|
285
|
+
\_\_class Car\n
|
|
286
286
|
\_\_\_\_include Mongoid::Document\n
|
|
287
|
-
\_\_\_\_has_one :
|
|
287
|
+
\_\_\_\_has_one :engine, class_name: \"Motor\", inverse_of: :machine\n
|
|
288
288
|
\_\_end\n\n
|
|
289
|
-
\_\_class
|
|
289
|
+
\_\_class Motor\n
|
|
290
290
|
\_\_\_\_include Mongoid::Document\n
|
|
291
|
-
\_\_\_\_belongs_to :
|
|
291
|
+
\_\_\_\_belongs_to :machine, class_name: \"Car\", inverse_of: :engine\n
|
|
292
292
|
\_\_end"
|
|
293
293
|
invalid_set_polymorphic_relation:
|
|
294
294
|
message: "The %{name} attribute can't be set to an instance of
|
data/lib/mongoid.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
require "support/ruby_version"
|
|
5
5
|
|
|
6
|
-
require "
|
|
6
|
+
require "forwardable"
|
|
7
7
|
require "time"
|
|
8
8
|
require "set"
|
|
9
9
|
|
|
@@ -36,6 +36,7 @@ end
|
|
|
36
36
|
I18n.load_path << File.join(File.dirname(__FILE__), "config", "locales", "en.yml")
|
|
37
37
|
|
|
38
38
|
module Mongoid
|
|
39
|
+
extend Forwardable
|
|
39
40
|
extend Loggable
|
|
40
41
|
extend self
|
|
41
42
|
|
|
@@ -109,5 +110,5 @@ module Mongoid
|
|
|
109
110
|
# Mongoid.database = Mongo::Connection.new.db("test")
|
|
110
111
|
#
|
|
111
112
|
# @since 1.0.0
|
|
112
|
-
|
|
113
|
+
def_delegators Config, *(Config.public_instance_methods(false) - [ :logger=, :logger ])
|
|
113
114
|
end
|
|
@@ -131,15 +131,50 @@ module Mongoid
|
|
|
131
131
|
# @api private
|
|
132
132
|
def _mongoid_filter_selected_fields(assoc_key)
|
|
133
133
|
return nil unless __selected_fields
|
|
134
|
+
|
|
135
|
+
projecting_assoc = false
|
|
136
|
+
|
|
134
137
|
filtered = {}
|
|
135
138
|
__selected_fields.each do |k, v|
|
|
136
139
|
bits = k.split('.')
|
|
140
|
+
|
|
141
|
+
# If we are asked to project an association, we need all of that
|
|
142
|
+
# association's fields. However, we may be asked to project
|
|
143
|
+
# an association *and* its fields in the same query. In this case
|
|
144
|
+
# behavior differs according to server version:
|
|
145
|
+
#
|
|
146
|
+
# 4.2 and lower take the most recent projection specification, meaning
|
|
147
|
+
# projecting foo followed by foo.bar effectively projects foo.bar and
|
|
148
|
+
# projecting foo.bar followed by foo effectively projects foo.
|
|
149
|
+
# To match this behavior we need to track when we are being asked
|
|
150
|
+
# to project the association and when we are asked to project a field,
|
|
151
|
+
# and if we are asked to project the association last we need to
|
|
152
|
+
# remove any field projections.
|
|
153
|
+
#
|
|
154
|
+
# 4.4 (and presumably higher) do not allow projection to be on an
|
|
155
|
+
# association and its field, so it doesn't matter what we do. Hence
|
|
156
|
+
# we just need to handle the 4.2 and lower case correctly.
|
|
137
157
|
if bits.first == assoc_key
|
|
138
|
-
|
|
139
|
-
|
|
158
|
+
# Projecting the entire association OR some of its fields
|
|
159
|
+
if bits.length > 1
|
|
160
|
+
# Projecting a field
|
|
161
|
+
bits.shift
|
|
162
|
+
filtered[bits.join('.')] = v
|
|
163
|
+
projecting_assoc = false
|
|
164
|
+
else
|
|
165
|
+
# Projecting the entire association
|
|
166
|
+
projecting_assoc = true
|
|
167
|
+
end
|
|
140
168
|
end
|
|
141
169
|
end
|
|
142
170
|
|
|
171
|
+
if projecting_assoc
|
|
172
|
+
# The last projection was of the entire association; we may have
|
|
173
|
+
# also been projecting fields, but discard the field projections
|
|
174
|
+
# and return nil indicating we want the entire association.
|
|
175
|
+
return nil
|
|
176
|
+
end
|
|
177
|
+
|
|
143
178
|
# Positional projection is specified as "foo.$". In this case the
|
|
144
179
|
# document that the $ is referring to should be retrieved with all
|
|
145
180
|
# fields. See https://docs.mongodb.com/manual/reference/operator/projection/positional/
|
|
@@ -200,7 +200,8 @@ module Mongoid
|
|
|
200
200
|
def determine_inverses(other)
|
|
201
201
|
matches = relation_class.relations.values.select do |rel|
|
|
202
202
|
relation_complements.include?(rel.class) &&
|
|
203
|
-
|
|
203
|
+
# https://jira.mongodb.org/browse/MONGOID-4882
|
|
204
|
+
rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
|
|
204
205
|
end
|
|
205
206
|
if matches.size > 1
|
|
206
207
|
raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
|
|
@@ -162,7 +162,8 @@ module Mongoid
|
|
|
162
162
|
def determine_inverses(other)
|
|
163
163
|
matches = relation_class.relations.values.select do |rel|
|
|
164
164
|
relation_complements.include?(rel.class) &&
|
|
165
|
-
|
|
165
|
+
# https://jira.mongodb.org/browse/MONGOID-4882
|
|
166
|
+
rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
|
|
166
167
|
|
|
167
168
|
end
|
|
168
169
|
if matches.size > 1
|
|
@@ -7,10 +7,11 @@ module Mongoid
|
|
|
7
7
|
# This is the superclass for all many to one and many to many association
|
|
8
8
|
# proxies.
|
|
9
9
|
class Many < Association::Proxy
|
|
10
|
+
extend Forwardable
|
|
10
11
|
include ::Enumerable
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
def_delegators :criteria, :avg, :max, :min, :sum
|
|
14
|
+
def_delegators :_target, :length, :size
|
|
14
15
|
|
|
15
16
|
# Is the association empty?
|
|
16
17
|
#
|
|
@@ -9,12 +9,14 @@ module Mongoid
|
|
|
9
9
|
# This class is the superclass for all association proxy objects, and contains
|
|
10
10
|
# common behavior for all of them.
|
|
11
11
|
class Proxy
|
|
12
|
+
extend Forwardable
|
|
13
|
+
|
|
12
14
|
alias :extend_proxy :extend
|
|
13
15
|
|
|
14
16
|
# We undefine most methods to get them sent through to the target.
|
|
15
17
|
instance_methods.each do |method|
|
|
16
18
|
undef_method(method) unless
|
|
17
|
-
method =~
|
|
19
|
+
method =~ /\A(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)\z/
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
include Threaded::Lifecycle
|
|
@@ -36,9 +38,9 @@ module Mongoid
|
|
|
36
38
|
attr_accessor :_target
|
|
37
39
|
|
|
38
40
|
# Backwards compatibility with Mongoid beta releases.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
def_delegators :_association, :foreign_key, :inverse_foreign_key
|
|
42
|
+
def_delegators :binding, :bind_one, :unbind_one
|
|
43
|
+
def_delegator :_base, :collection_name
|
|
42
44
|
|
|
43
45
|
# Convenience for setting the target and the association metadata properties since
|
|
44
46
|
# all proxies will need to do this.
|
|
@@ -76,7 +76,7 @@ module Mongoid
|
|
|
76
76
|
# @since 3.0.0
|
|
77
77
|
def check_polymorphic_inverses!(doc)
|
|
78
78
|
inverses = _association.inverses(doc)
|
|
79
|
-
if inverses.
|
|
79
|
+
if inverses.length > 1 && _base.send(_association.foreign_key).nil?
|
|
80
80
|
raise Errors::InvalidSetPolymorphicRelation.new(
|
|
81
81
|
_association.name, _base.class.name, _target.class.name
|
|
82
82
|
)
|
|
@@ -12,8 +12,6 @@ module Mongoid
|
|
|
12
12
|
private
|
|
13
13
|
|
|
14
14
|
def preload
|
|
15
|
-
raise Errors::EagerLoad.new(@association.name) if @association.polymorphic?
|
|
16
|
-
|
|
17
15
|
@docs.each do |d|
|
|
18
16
|
set_relation(d, nil)
|
|
19
17
|
end
|
|
@@ -24,6 +22,44 @@ module Mongoid
|
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
|
|
25
|
+
# Retrieves the documents referenced by the association, and
|
|
26
|
+
# yields each one sequentially to the provided block. If the
|
|
27
|
+
# association is not polymorphic, all documents are retrieved in
|
|
28
|
+
# a single query. If the association is polymorphic, one query is
|
|
29
|
+
# issued per association target class.
|
|
30
|
+
def each_loaded_document(&block)
|
|
31
|
+
if @association.polymorphic?
|
|
32
|
+
keys_by_type_from_docs.each do |type, keys|
|
|
33
|
+
each_loaded_document_of_class(Object.const_get(type), keys, &block)
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns a map from association target class name to foreign key
|
|
41
|
+
# values for the documents of that association target class,
|
|
42
|
+
# as referenced by this association.
|
|
43
|
+
def keys_by_type_from_docs
|
|
44
|
+
inverse_type_field = @association.inverse_type
|
|
45
|
+
|
|
46
|
+
@docs.each_with_object({}) do |doc, keys_by_type|
|
|
47
|
+
next unless doc.respond_to?(inverse_type_field) && doc.respond_to?(group_by_key)
|
|
48
|
+
inverse_type_name = doc.send(inverse_type_field)
|
|
49
|
+
# If a particular document does not have a value for this
|
|
50
|
+
# association, inverse_type_name will be nil.
|
|
51
|
+
next if inverse_type_name.nil?
|
|
52
|
+
|
|
53
|
+
key_value = doc.send(group_by_key)
|
|
54
|
+
# If a document has the *_type field set but the corresponding
|
|
55
|
+
# *_id field not set, the key value here will be nil.
|
|
56
|
+
next unless key_value
|
|
57
|
+
|
|
58
|
+
keys_by_type[inverse_type_name] ||= []
|
|
59
|
+
keys_by_type[inverse_type_name].push(key_value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
27
63
|
def group_by_key
|
|
28
64
|
@association.foreign_key
|
|
29
65
|
end
|
|
@@ -59,17 +59,29 @@ module Mongoid
|
|
|
59
59
|
raise NotImplementedError
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
62
|
+
# Retrieves the documents referenced by the association, and
|
|
63
|
+
# yields each one sequentially to the provided block. If the
|
|
64
|
+
# association is not polymorphic, all documents are retrieved in
|
|
65
|
+
# a single query. If the association is polymorphic, one query is
|
|
66
|
+
# issued per association target class.
|
|
66
67
|
#
|
|
67
68
|
# @since 4.0.0
|
|
68
|
-
def each_loaded_document
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
def each_loaded_document(&block)
|
|
70
|
+
each_loaded_document_of_class(@association.klass, keys_from_docs, &block)
|
|
71
|
+
end
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
# Retrieves the documents of the specified class, that have the
|
|
74
|
+
# foreign key included in the specified list of keys.
|
|
75
|
+
#
|
|
76
|
+
# When the documents are retrieved, the set of inclusions applied
|
|
77
|
+
# is the set of inclusions applied to the host document minus the
|
|
78
|
+
# association that is being eagerly loaded.
|
|
79
|
+
private def each_loaded_document_of_class(cls, keys)
|
|
80
|
+
# Note: keys should not include nil elements.
|
|
81
|
+
# Upstream code is responsible for eliminating nils from keys.
|
|
82
|
+
return cls.none if keys.empty?
|
|
83
|
+
|
|
84
|
+
criteria = cls.any_in(key => keys)
|
|
73
85
|
criteria.inclusions = criteria.inclusions - [@association]
|
|
74
86
|
criteria.each do |doc|
|
|
75
87
|
yield doc
|
|
@@ -93,6 +105,9 @@ module Mongoid
|
|
|
93
105
|
|
|
94
106
|
# Return a hash with the current documents grouped by key.
|
|
95
107
|
#
|
|
108
|
+
# Documents that do not have a value for the association being loaded
|
|
109
|
+
# are not returned.
|
|
110
|
+
#
|
|
96
111
|
# @example Return a hash with the current documents grouped by key.
|
|
97
112
|
# loader.grouped_docs
|
|
98
113
|
#
|
|
@@ -102,10 +117,15 @@ module Mongoid
|
|
|
102
117
|
def grouped_docs
|
|
103
118
|
@grouped_docs[@association.name] ||= @docs.group_by do |doc|
|
|
104
119
|
doc.send(group_by_key) if doc.respond_to?(group_by_key)
|
|
120
|
+
end.reject do |k, v|
|
|
121
|
+
k.nil?
|
|
105
122
|
end
|
|
106
123
|
end
|
|
107
124
|
|
|
108
|
-
# Group the documents and return the keys
|
|
125
|
+
# Group the documents and return the keys.
|
|
126
|
+
#
|
|
127
|
+
# This method omits nil keys (i.e. keys from documents that do not
|
|
128
|
+
# have a value for the association being loaded).
|
|
109
129
|
#
|
|
110
130
|
# @example
|
|
111
131
|
# loader.keys_from_docs
|
|
@@ -11,6 +11,7 @@ module Mongoid
|
|
|
11
11
|
# target that can be a criteria or array of _loaded documents. This
|
|
12
12
|
# handles both cases or a combination of the two.
|
|
13
13
|
class Enumerable
|
|
14
|
+
extend Forwardable
|
|
14
15
|
include ::Enumerable
|
|
15
16
|
|
|
16
17
|
# The three main instance variables are collections of documents.
|
|
@@ -20,7 +21,7 @@ module Mongoid
|
|
|
20
21
|
# @attribute [rw] _unloaded A criteria representing persisted docs.
|
|
21
22
|
attr_accessor :_added, :_loaded, :_unloaded
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
def_delegators [], :is_a?, :kind_of?
|
|
24
25
|
|
|
25
26
|
# Check if the enumerable is equal to the other object.
|
|
26
27
|
#
|
|
@@ -215,27 +216,6 @@ module Mongoid
|
|
|
215
216
|
end
|
|
216
217
|
end
|
|
217
218
|
|
|
218
|
-
# Get an arbitrary document in the enumerable. Will check the persisted
|
|
219
|
-
# documents first. Does not load the entire enumerable.
|
|
220
|
-
#
|
|
221
|
-
# @example Get an arbitrary document.
|
|
222
|
-
# enumerable.one
|
|
223
|
-
#
|
|
224
|
-
# @note Unlike #first, this does not automatically sort the result set.
|
|
225
|
-
#
|
|
226
|
-
# @param [ Hash ] opts The options for the query returning the first document.
|
|
227
|
-
#
|
|
228
|
-
# @option opts [ :none ] :id_sort Don't apply a sort on _id.
|
|
229
|
-
#
|
|
230
|
-
# @return [ Document ] The first document found.
|
|
231
|
-
#
|
|
232
|
-
# @since 7.1.0
|
|
233
|
-
def one(opts = {})
|
|
234
|
-
opts = opts.dup
|
|
235
|
-
opts[:id_sort] ||= :none
|
|
236
|
-
first(opts)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
219
|
# Get the first document in the enumerable. Will check the persisted
|
|
240
220
|
# documents first. Does not load the entire enumerable.
|
|
241
221
|
#
|