mongoid 9.0.0 → 9.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/Rakefile +44 -21
- data/lib/config/locales/en.yml +20 -0
- data/lib/mongoid/association/accessors.rb +7 -2
- data/lib/mongoid/association/nested/one.rb +14 -1
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +7 -1
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/belongs_to.rb +15 -0
- data/lib/mongoid/association/referenced/has_many.rb +9 -8
- data/lib/mongoid/association/referenced/has_one/buildable.rb +3 -8
- data/lib/mongoid/association/referenced/with_polymorphic_criteria.rb +41 -0
- data/lib/mongoid/atomic_update_preparer.rb +7 -6
- data/lib/mongoid/attributes/nested.rb +2 -1
- data/lib/mongoid/clients/sessions.rb +12 -15
- data/lib/mongoid/composable.rb +2 -0
- data/lib/mongoid/config.rb +9 -0
- data/lib/mongoid/contextual/aggregable/memory.rb +3 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +5 -2
- data/lib/mongoid/criteria/findable.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -1
- data/lib/mongoid/document.rb +2 -0
- data/lib/mongoid/errors/invalid_around_callback.rb +16 -0
- data/lib/mongoid/errors/unrecognized_model_alias.rb +53 -0
- data/lib/mongoid/errors/unrecognized_resolver.rb +27 -0
- data/lib/mongoid/errors/unregistered_class.rb +47 -0
- data/lib/mongoid/errors.rb +4 -0
- data/lib/mongoid/fields.rb +13 -7
- data/lib/mongoid/identifiable.rb +28 -0
- data/lib/mongoid/interceptable.rb +18 -13
- data/lib/mongoid/model_resolver.rb +154 -0
- data/lib/mongoid/persistence_context.rb +2 -1
- data/lib/mongoid/scopable.rb +7 -1
- data/lib/mongoid/touchable.rb +1 -7
- data/lib/mongoid/traversable.rb +5 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/associations/belongs_to_spec.rb +129 -0
- data/spec/integration/persistence/collection_options_spec.rb +36 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +4 -0
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +1 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +58 -21
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +4 -0
- data/spec/mongoid/association_spec.rb +14 -0
- data/spec/mongoid/attributes/nested_spec.rb +1 -0
- data/spec/mongoid/attributes_spec.rb +16 -0
- data/spec/mongoid/clients/transactions_spec.rb +2 -2
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +11 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +11 -0
- data/spec/mongoid/contextual/mongo_spec.rb +72 -3
- data/spec/mongoid/fields_spec.rb +2 -2
- data/spec/mongoid/interceptable_spec.rb +31 -0
- data/spec/mongoid/model_resolver_spec.rb +167 -0
- data/spec/mongoid/monkey_patches_spec.rb +1 -1
- data/spec/mongoid/persistence_context_spec.rb +17 -4
- data/spec/mongoid/scopable_spec.rb +88 -85
- data/spec/mongoid/serializable_spec.rb +16 -9
- data/spec/mongoid/touchable_spec.rb +75 -0
- data/spec/mongoid/touchable_spec_models.rb +16 -0
- data/spec/support/models/band.rb +1 -0
- data/spec/support/models/lat_lng.rb +6 -0
- metadata +20 -82
- checksums.yaml.gz.sig +0 -1
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/bin/s3-copy +0 -45
- data/spec/shared/bin/s3-upload +0 -69
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -231
- data/spec/shared/lib/mrss/constraints.rb +0 -378
- data/spec/shared/lib/mrss/docker_runner.rb +0 -298
- data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
- data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
- data/spec/shared/lib/mrss/session_registry.rb +0 -69
- data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
- data/spec/shared/lib/mrss/utils.rb +0 -37
- data/spec/shared/share/Dockerfile.erb +0 -281
- data/spec/shared/share/haproxy-1.conf +0 -16
- data/spec/shared/share/haproxy-2.conf +0 -17
- data/spec/shared/shlib/config.sh +0 -27
- data/spec/shared/shlib/distro.sh +0 -74
- data/spec/shared/shlib/server.sh +0 -417
- data/spec/shared/shlib/set_env.sh +0 -146
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 558b30b0a39cd36cd9a3e54695f4617a9fcc0d67300637d1299b487b7d911bda
|
4
|
+
data.tar.gz: eccf9c55bdde17fd38592427e0dd6b5545d3e605b94a4308a422ba332e20c183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 420ac9d23abeecb04c19794df124fc80d4f99883e1156d4e3be42e79b4b2e5e5a558c6b650746784024f0477a800def3a2ded537b848d3e9b97fb5e5e220b1f0
|
7
|
+
data.tar.gz: 40bfdcaf862e3ae7d3d046d84d5f9f5eea4752b5559c869eda16e1bd00cbc9aaae3eef05a7e4bec497915619fb162a248ac8f4be3525068e81f28ae876af1a29
|
data/README.md
CHANGED
@@ -14,6 +14,8 @@ Mongoid has [extensive user documentation](https://www.mongodb.com/docs/mongoid/
|
|
14
14
|
Mongoid is built on top of the MongoDB Ruby driver which has
|
15
15
|
[its own user documentation](https://www.mongodb.com/docs/ruby-driver/current/).
|
16
16
|
|
17
|
+
High-level Mongoid documentation including tutorials and the reference that were in the docs folder can now be found at the docs-mongoid repository, [here](https://github.com/mongodb/docs-mongoid).
|
18
|
+
|
17
19
|
Compatibility
|
18
20
|
-------------
|
19
21
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
# rubocop:todo all
|
3
3
|
|
4
4
|
require "bundler"
|
5
|
-
require "bundler/gem_tasks"
|
6
5
|
Bundler.setup
|
7
6
|
|
8
7
|
ROOT = File.expand_path(File.join(File.dirname(__FILE__)))
|
@@ -11,25 +10,53 @@ $: << File.join(ROOT, 'spec/shared/lib')
|
|
11
10
|
|
12
11
|
require "rake"
|
13
12
|
require "rspec/core/rake_task"
|
14
|
-
require 'mrss/spec_organizer'
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
tasks['release:do'] = tasks.delete('release')
|
21
|
-
|
22
|
-
task :gem => :build
|
14
|
+
# stands in for the Bundler-provided `build` task, which builds the
|
15
|
+
# gem for this project. Our release process builds the gems in a
|
16
|
+
# particular way, in a GitHub action. This task is just to help remind
|
17
|
+
# developers of that fact.
|
23
18
|
task :build do
|
24
|
-
|
19
|
+
abort <<~WARNING
|
20
|
+
`rake build` does nothing in this project. The gem must be built via
|
21
|
+
the `Mongoid Release` action on GitHub, which is triggered manually when
|
22
|
+
a new release is ready.
|
23
|
+
WARNING
|
25
24
|
end
|
26
25
|
|
27
|
-
|
28
|
-
|
26
|
+
# `rake version` is used by the deployment system so get the release version
|
27
|
+
# of the product beng deployed. It must do nothing more than just print the
|
28
|
+
# product version number.
|
29
|
+
#
|
30
|
+
# See the mongodb-labs/driver-github-tools/ruby/publish Github action.
|
31
|
+
desc "Print the current value of Mongoid::VERSION"
|
32
|
+
task :version do
|
33
|
+
require 'mongoid/version'
|
34
|
+
|
35
|
+
puts Mongoid::VERSION
|
29
36
|
end
|
30
37
|
|
38
|
+
# overrides the default Bundler-provided `release` task, which also
|
39
|
+
# builds the gem. Our release process assumes the gem has already
|
40
|
+
# been built (and signed via GPG), so we just need `rake release` to
|
41
|
+
# push the gem to rubygems.
|
31
42
|
task :release do
|
32
|
-
|
43
|
+
require 'mongoid/version'
|
44
|
+
|
45
|
+
if ENV['GITHUB_ACTION'].nil?
|
46
|
+
abort <<~WARNING
|
47
|
+
`rake release` must be invoked from the `Mongoid Release` GitHub action,
|
48
|
+
and must not be invoked locally. This ensures the gem is properly signed
|
49
|
+
and distributed by the appropriate user.
|
50
|
+
|
51
|
+
Note that it is the `rubygems/release-gem@v1` step in the `Mongoid Release`
|
52
|
+
action that invokes this task. Do not rename or remove this task, or the
|
53
|
+
release-gem step will fail. Reimplement this task with caution.
|
54
|
+
|
55
|
+
mongoid-#{Mongoid::VERSION}.gem was NOT pushed to RubyGems.
|
56
|
+
WARNING
|
57
|
+
end
|
58
|
+
|
59
|
+
system 'gem', 'push', "mongoid-#{Mongoid::VERSION}.gem"
|
33
60
|
end
|
34
61
|
|
35
62
|
RSpec::Core::RakeTask.new("spec") do |spec|
|
@@ -96,6 +123,8 @@ RUN_PRIORITY = %i(
|
|
96
123
|
)
|
97
124
|
|
98
125
|
def spec_organizer
|
126
|
+
require 'mrss/spec_organizer'
|
127
|
+
|
99
128
|
Mrss::SpecOrganizer.new(
|
100
129
|
root: ROOT,
|
101
130
|
classifiers: CLASSIFIERS,
|
@@ -131,16 +160,10 @@ task :docs => 'docs:yard'
|
|
131
160
|
namespace :docs do
|
132
161
|
desc "Generate yard documentation"
|
133
162
|
task :yard do
|
163
|
+
require "mongoid/version"
|
164
|
+
|
134
165
|
out = File.join('yard-docs', Mongoid::VERSION)
|
135
166
|
FileUtils.rm_rf(out)
|
136
167
|
system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
|
137
168
|
end
|
138
169
|
end
|
139
|
-
|
140
|
-
namespace :release do
|
141
|
-
task :check_private_key do
|
142
|
-
unless File.exist?('gem-private_key.pem')
|
143
|
-
raise "No private key present, cannot release"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
data/lib/config/locales/en.yml
CHANGED
@@ -140,6 +140,10 @@ en:
|
|
140
140
|
A collation option is only supported if the query is executed on a MongoDB server
|
141
141
|
with version >= 3.4."
|
142
142
|
resolution: "Remove the collation option from the query."
|
143
|
+
invalid_around_callback:
|
144
|
+
message: "An around callback must contain a yield in its definition."
|
145
|
+
summary: "The block needs to be yielded to for around callbacks to function as intended."
|
146
|
+
resolution: "Ensure there is a yield statement inside the body of the around callback."
|
143
147
|
invalid_async_query_executor:
|
144
148
|
message: "Invalid async_query_executor option: %{executor}."
|
145
149
|
summary: "A invalid async query executor was specified.
|
@@ -676,6 +680,22 @@ en:
|
|
676
680
|
resolution: "The _type field is a reserved one used by Mongoid to determine the
|
677
681
|
class for instantiating an object. Please don't save data in this field or ensure
|
678
682
|
that any values in this field correspond to valid models."
|
683
|
+
unrecognized_model_alias:
|
684
|
+
message: "Cannot find any model with type %{model_alias}"
|
685
|
+
summary: "A document is trying to load a polymorphic association, but the data refers to a type of object that can't be resolved (%{model_alias}). It might be that you've renamed the target class."
|
686
|
+
resolution: "Register the old name as an alias on the refactored target object, using `identify_as`. This will allow Mongoid to find the target type even if the name no longer matches what was stored in the database."
|
687
|
+
unrecognized_resolver:
|
688
|
+
message: "The model resolver %{resolver} was referenced, but never registered."
|
689
|
+
summary: "A polymorphic association has been configured to use a resolver
|
690
|
+
named %{resolver}, but that resolver has not yet been registered. This
|
691
|
+
might be a typo. Currently registered resolvers are: %{resolvers}."
|
692
|
+
resolution: "Register custom resolvers with
|
693
|
+
`Mongoid::ModelResolver.register_resolver` before attempting to query
|
694
|
+
a polymorphic association."
|
695
|
+
unregistered_class:
|
696
|
+
message: "The class %{klass} is not registered with the resolver %{resolver}."
|
697
|
+
summary: "A polymorphic association using the resolver %{resolver} has tried to link to a model of type %{klass}, but the resolver has no knowledge of any such model. This can happen if the association is configured to use a different resolver than the target mode."
|
698
|
+
resolution: "Make sure the target model is registered with the same resolver as the polymorphic association, using `identify_as`."
|
679
699
|
unsaved_document:
|
680
700
|
message: "Attempted to save %{document} before the parent %{base}."
|
681
701
|
summary: "You cannot call create or create! through the
|
@@ -42,7 +42,8 @@ module Mongoid
|
|
42
42
|
#
|
43
43
|
# @return [ Proxy ] The association.
|
44
44
|
def create_relation(object, association, selected_fields = nil)
|
45
|
-
|
45
|
+
key = @attributes[association.inverse_type]
|
46
|
+
type = key ? association.resolver.model_for(key) : nil
|
46
47
|
target = if t = association.build(self, object, type, selected_fields)
|
47
48
|
association.create_relation(self, t)
|
48
49
|
else
|
@@ -116,7 +117,11 @@ module Mongoid
|
|
116
117
|
# during binding or when cascading callbacks. Whenever we retrieve
|
117
118
|
# associations within the codebase, we use without_autobuild.
|
118
119
|
if !without_autobuild? && association.embedded? && attribute_missing?(field_name)
|
119
|
-
|
120
|
+
# We always allow accessing the parent document of an embedded one.
|
121
|
+
try_get_parent = association.is_a?(
|
122
|
+
Mongoid::Association::Embedded::EmbeddedIn
|
123
|
+
) && field_name == association.key
|
124
|
+
raise Mongoid::Errors::AttributeNotLoaded.new(self.class, field_name) unless try_get_parent
|
120
125
|
end
|
121
126
|
|
122
127
|
if !reload && (value = ivar(name)) != false
|
@@ -53,12 +53,25 @@ module Mongoid
|
|
53
53
|
@attributes = attributes.with_indifferent_access
|
54
54
|
@association = association
|
55
55
|
@options = options
|
56
|
-
@class_name = options[:class_name]
|
56
|
+
@class_name = class_from(options[:class_name])
|
57
57
|
@destroy = @attributes.delete(:_destroy)
|
58
58
|
end
|
59
59
|
|
60
60
|
private
|
61
61
|
|
62
|
+
# Coerces the argument into a class, or defaults to the association's class.
|
63
|
+
#
|
64
|
+
# @param [ String | Mongoid::Document | nil ] name_or_class the value to coerce
|
65
|
+
#
|
66
|
+
# @return [ Mongoid::Document ] the resulting class
|
67
|
+
def class_from(name_or_class)
|
68
|
+
case name_or_class
|
69
|
+
when nil, false then association.klass
|
70
|
+
when String then name_or_class.constantize
|
71
|
+
else name_or_class
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
62
75
|
# Extracts and converts the id to the expected type.
|
63
76
|
#
|
64
77
|
# @return [ BSON::ObjectId | String | Object | nil ] The converted id,
|
@@ -23,7 +23,13 @@ module Mongoid
|
|
23
23
|
binding do
|
24
24
|
check_polymorphic_inverses!(_target)
|
25
25
|
bind_foreign_key(_base, record_id(_target))
|
26
|
-
|
26
|
+
|
27
|
+
# set the inverse type (e.g. "#{name}_type") for new polymorphic associations
|
28
|
+
if _association.inverse_type && !_base.frozen?
|
29
|
+
key = _association.resolver.default_key_for(_target)
|
30
|
+
bind_polymorphic_inverse_type(_base, key)
|
31
|
+
end
|
32
|
+
|
27
33
|
if inverse = _association.inverse(_target)
|
28
34
|
if set_base_association
|
29
35
|
if _base.referenced_many?
|
@@ -33,7 +33,7 @@ module Mongoid
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def query_criteria(object, type)
|
36
|
-
cls = type ? type.constantize : relation_class
|
36
|
+
cls = type ? (type.is_a?(String) ? type.constantize : type) : relation_class
|
37
37
|
crit = cls.criteria
|
38
38
|
crit = crit.apply_scope(scope)
|
39
39
|
crit.where(primary_key => object)
|
@@ -103,6 +103,21 @@ module Mongoid
|
|
103
103
|
@polymorphic ||= !!@options[:polymorphic]
|
104
104
|
end
|
105
105
|
|
106
|
+
# Returns the object responsible for converting polymorphic type references into
|
107
|
+
# class objects, and vice versa. This is obtained via the `:polymorphic` option
|
108
|
+
# that was given when the association was defined.
|
109
|
+
#
|
110
|
+
# See Mongoid::ModelResolver.resolver for how the `:polymorphic` option is
|
111
|
+
# interpreted here.
|
112
|
+
#
|
113
|
+
# @raise KeyError if no such resolver has been registered under the given
|
114
|
+
# identifier.
|
115
|
+
#
|
116
|
+
# @return [ nil | Mongoid::ModelResolver ] the resolver to use
|
117
|
+
def resolver
|
118
|
+
@resolver ||= Mongoid::ModelResolver.resolver(@options[:polymorphic])
|
119
|
+
end
|
120
|
+
|
106
121
|
# The name of the field used to store the type of polymorphic association.
|
107
122
|
#
|
108
123
|
# @return [ String ] The field used to store the type of polymorphic association.
|
@@ -6,6 +6,7 @@ require 'mongoid/association/referenced/has_many/buildable'
|
|
6
6
|
require 'mongoid/association/referenced/has_many/proxy'
|
7
7
|
require 'mongoid/association/referenced/has_many/enumerable'
|
8
8
|
require 'mongoid/association/referenced/has_many/eager'
|
9
|
+
require 'mongoid/association/referenced/with_polymorphic_criteria'
|
9
10
|
|
10
11
|
module Mongoid
|
11
12
|
module Association
|
@@ -15,6 +16,7 @@ module Mongoid
|
|
15
16
|
class HasMany
|
16
17
|
include Relatable
|
17
18
|
include Buildable
|
19
|
+
include WithPolymorphicCriteria
|
18
20
|
|
19
21
|
# The options available for this type of association, in addition to the
|
20
22
|
# common ones.
|
@@ -131,6 +133,12 @@ module Mongoid
|
|
131
133
|
# @param [ Class ] object_class The object class.
|
132
134
|
#
|
133
135
|
# @return [ Mongoid::Criteria ] The criteria object.
|
136
|
+
#
|
137
|
+
# @deprecated in 9.0.x
|
138
|
+
#
|
139
|
+
# It appears as if this method is an artifact left over from a refactoring that renamed it
|
140
|
+
# `with_polymorphic_criterion`, and made it private. Regardless, this method isn't referenced
|
141
|
+
# anywhere else, and is unlikely to be useful to external clients. We should remove it.
|
134
142
|
def add_polymorphic_criterion(criteria, object_class)
|
135
143
|
if polymorphic?
|
136
144
|
criteria.where(type => object_class.name)
|
@@ -138,6 +146,7 @@ module Mongoid
|
|
138
146
|
criteria
|
139
147
|
end
|
140
148
|
end
|
149
|
+
Mongoid.deprecate(self, :add_polymorphic_criterion)
|
141
150
|
|
142
151
|
# Is this association polymorphic?
|
143
152
|
#
|
@@ -222,14 +231,6 @@ module Mongoid
|
|
222
231
|
with_ordering(crit)
|
223
232
|
end
|
224
233
|
|
225
|
-
def with_polymorphic_criterion(criteria, base)
|
226
|
-
if polymorphic?
|
227
|
-
criteria.where(type => base.class.name)
|
228
|
-
else
|
229
|
-
criteria
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
234
|
def with_ordering(criteria)
|
234
235
|
if order
|
235
236
|
criteria.order_by(order)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# rubocop:todo all
|
3
3
|
|
4
|
+
require 'mongoid/association/referenced/with_polymorphic_criteria'
|
5
|
+
|
4
6
|
module Mongoid
|
5
7
|
module Association
|
6
8
|
module Referenced
|
@@ -8,6 +10,7 @@ module Mongoid
|
|
8
10
|
|
9
11
|
# The Builder behavior for has_one associations.
|
10
12
|
module Buildable
|
13
|
+
include WithPolymorphicCriteria
|
11
14
|
|
12
15
|
# This method either takes an _id or an object and queries for the
|
13
16
|
# inverse side using the id or sets the object after clearing the
|
@@ -57,14 +60,6 @@ module Mongoid
|
|
57
60
|
query_criteria(object, base).take
|
58
61
|
end
|
59
62
|
|
60
|
-
def with_polymorphic_criterion(criteria, base)
|
61
|
-
if polymorphic?
|
62
|
-
criteria.where(type => base.class.name)
|
63
|
-
else
|
64
|
-
criteria
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
63
|
def query?(object)
|
69
64
|
object && !object.is_a?(Mongoid::Document)
|
70
65
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Association
|
5
|
+
module Referenced
|
6
|
+
# Implements the `with_polymorphic_criteria` shared behavior.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
module WithPolymorphicCriteria
|
10
|
+
# If the receiver represents a polymorphic association, applies
|
11
|
+
# the polymorphic search criteria to the given `criteria` object.
|
12
|
+
#
|
13
|
+
# @param [ Mongoid::Criteria ] criteria the criteria to append to
|
14
|
+
# if receiver is polymorphic.
|
15
|
+
# @param [ Mongoid::Document ] base the document to use when resolving
|
16
|
+
# the polymorphic type keys.
|
17
|
+
#
|
18
|
+
# @return [ Mongoid::Criteria] the resulting criteria, which may be
|
19
|
+
# the same as the input.
|
20
|
+
def with_polymorphic_criterion(criteria, base)
|
21
|
+
if polymorphic?
|
22
|
+
# 1. get the resolver for the inverse association
|
23
|
+
resolver = klass.reflect_on_association(as).resolver
|
24
|
+
|
25
|
+
# 2. look up the list of keys from the resolver, given base
|
26
|
+
keys = resolver.keys_for(base)
|
27
|
+
|
28
|
+
# 3. use equality if there is just one key, `in` if there are multiple
|
29
|
+
if keys.many?
|
30
|
+
criteria.where(type => { :$in => keys })
|
31
|
+
else
|
32
|
+
criteria.where(type => keys.first)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
criteria
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -25,7 +25,7 @@ module Mongoid
|
|
25
25
|
if key.to_s.start_with?('$')
|
26
26
|
(atomic_updates[key] ||= {}).update(prepare_operation(klass, key, value))
|
27
27
|
else
|
28
|
-
(atomic_updates['$set'] ||= {})[key] = mongoize_for(
|
28
|
+
(atomic_updates['$set'] ||= {})[key] = mongoize_for('$set', klass, key, value)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -43,24 +43,25 @@ module Mongoid
|
|
43
43
|
def prepare_operation(klass, key, value)
|
44
44
|
value.each_with_object({}) do |(key2, value2), hash|
|
45
45
|
key2 = klass.database_field_name(key2)
|
46
|
-
hash[key2] = value_for(key, klass, value2)
|
46
|
+
hash[key2] = value_for(key, klass, key2, value2)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
# Get the value for the provided operator, klass, key and value.
|
51
51
|
#
|
52
|
-
# This is necessary for special cases like $rename, $addToSet and $
|
52
|
+
# This is necessary for special cases like $rename, $addToSet, $push, $pull and $pop.
|
53
53
|
#
|
54
54
|
# @param [ String ] operator The operator.
|
55
55
|
# @param [ Class ] klass The model class.
|
56
|
+
# @param [ String | Symbol ] key The field key.
|
56
57
|
# @param [ Object ] value The original value.
|
57
58
|
#
|
58
59
|
# @return [ Object ] Value prepared for the provided operator.
|
59
|
-
def value_for(operator, klass, value)
|
60
|
+
def value_for(operator, klass, key, value)
|
60
61
|
case operator
|
61
62
|
when '$rename' then value.to_s
|
62
|
-
when '$addToSet', '$push' then value.mongoize
|
63
|
-
else mongoize_for(operator, klass,
|
63
|
+
when '$addToSet', '$push', '$pull', '$pop' then value.mongoize
|
64
|
+
else mongoize_for(operator, klass, key, value)
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -60,7 +60,8 @@ module Mongoid
|
|
60
60
|
re_define_method(meth) do |attrs|
|
61
61
|
_assigning do
|
62
62
|
if association.polymorphic? and association.inverse_type
|
63
|
-
|
63
|
+
klass = association.resolver.model_for(send(association.inverse_type))
|
64
|
+
options = options.merge!(:class_name => klass)
|
64
65
|
end
|
65
66
|
association.nested_builder(attrs, options).build(self)
|
66
67
|
end
|
@@ -89,21 +89,22 @@ module Mongoid
|
|
89
89
|
def transaction(options = {}, session_options: {})
|
90
90
|
with_session(session_options) do |session|
|
91
91
|
begin
|
92
|
-
session.
|
93
|
-
|
94
|
-
|
92
|
+
session.with_transaction(options) do
|
93
|
+
yield
|
94
|
+
end
|
95
|
+
run_commit_callbacks(session)
|
95
96
|
rescue *transactions_not_supported_exceptions
|
96
97
|
raise Mongoid::Errors::TransactionsNotSupported
|
97
98
|
rescue Mongoid::Errors::Rollback
|
98
|
-
|
99
|
+
run_abort_callbacks(session)
|
99
100
|
rescue Mongoid::Errors::InvalidSessionNesting
|
100
101
|
# Session should be ended here.
|
101
102
|
raise Mongoid::Errors::InvalidTransactionNesting.new
|
102
103
|
rescue Mongo::Error::InvalidSession, Mongo::Error::InvalidTransactionOperation => e
|
103
|
-
|
104
|
-
raise Mongoid::Errors::TransactionError(e)
|
104
|
+
run_abort_callbacks(session)
|
105
|
+
raise Mongoid::Errors::TransactionError.new(e)
|
105
106
|
rescue StandardError => e
|
106
|
-
|
107
|
+
run_abort_callbacks(session)
|
107
108
|
raise e
|
108
109
|
end
|
109
110
|
end
|
@@ -189,25 +190,21 @@ module Mongoid
|
|
189
190
|
_session&.in_transaction? || false
|
190
191
|
end
|
191
192
|
|
192
|
-
#
|
193
|
-
# after_commit callbacks on modified documents.
|
193
|
+
# Runs after_commit callbacks on modified documents.
|
194
194
|
#
|
195
195
|
# @param [ Mongo::Session ] session Session on which
|
196
196
|
# a transaction is started.
|
197
|
-
def
|
198
|
-
session.commit_transaction
|
197
|
+
def run_commit_callbacks(session)
|
199
198
|
Threaded.clear_modified_documents(session).each do |doc|
|
200
199
|
doc.run_after_callbacks(:commit)
|
201
200
|
end
|
202
201
|
end
|
203
202
|
|
204
|
-
#
|
205
|
-
# after_rollback callbacks on modified documents.
|
203
|
+
# Runs after_rollback callbacks on modified documents.
|
206
204
|
#
|
207
205
|
# @param [ Mongo::Session ] session Session on which
|
208
206
|
# a transaction is started.
|
209
|
-
def
|
210
|
-
session.abort_transaction
|
207
|
+
def run_abort_callbacks(session)
|
211
208
|
Threaded.clear_modified_documents(session).each do |doc|
|
212
209
|
doc.run_after_callbacks(:rollback)
|
213
210
|
end
|
data/lib/mongoid/composable.rb
CHANGED
@@ -5,6 +5,7 @@ require "mongoid/changeable"
|
|
5
5
|
require "mongoid/collection_configurable"
|
6
6
|
require "mongoid/encryptable"
|
7
7
|
require "mongoid/findable"
|
8
|
+
require 'mongoid/identifiable'
|
8
9
|
require "mongoid/indexable"
|
9
10
|
require "mongoid/inspectable"
|
10
11
|
require "mongoid/interceptable"
|
@@ -44,6 +45,7 @@ module Mongoid
|
|
44
45
|
include Attributes
|
45
46
|
include Evolvable
|
46
47
|
include Fields
|
48
|
+
include Identifiable
|
47
49
|
include Indexable
|
48
50
|
include Inspectable
|
49
51
|
include Matchable
|
data/lib/mongoid/config.rb
CHANGED
@@ -171,6 +171,15 @@ module Mongoid
|
|
171
171
|
# See https://jira.mongodb.org/browse/MONGOID-5658 for more details.
|
172
172
|
option :around_callbacks_for_embeds, default: false
|
173
173
|
|
174
|
+
# When this flag is false, named scopes cannot unset a default scope.
|
175
|
+
# This is the traditional (and default) behavior in Mongoid 9 and earlier.
|
176
|
+
#
|
177
|
+
# Setting this flag to true will allow named scopes to unset the default
|
178
|
+
# scope. This will be the default in Mongoid 10.
|
179
|
+
#
|
180
|
+
# See https://jira.mongodb.org/browse/MONGOID-5785 for more details.
|
181
|
+
option :allow_scopes_to_unset_default_scope, default: false
|
182
|
+
|
174
183
|
# Returns the Config singleton, for use in the configure DSL.
|
175
184
|
#
|
176
185
|
# @return [ self ] The Config singleton.
|
@@ -90,11 +90,12 @@ module Mongoid
|
|
90
90
|
# @example Get the sum for the provided block.
|
91
91
|
# aggregable.sum(&:likes)
|
92
92
|
#
|
93
|
-
# @param [ Symbol ] field The field to sum
|
93
|
+
# @param [ Symbol | Numeric ] field The field to sum, or the intial
|
94
|
+
# value of the sum when a block is given.
|
94
95
|
#
|
95
96
|
# @return [ Numeric ] The sum value.
|
96
97
|
def sum(field = nil)
|
97
|
-
return super() if block_given?
|
98
|
+
return super(field || 0) if block_given?
|
98
99
|
|
99
100
|
aggregate_by(field, :sum) || 0
|
100
101
|
end
|
@@ -96,11 +96,14 @@ module Mongoid
|
|
96
96
|
# @example Get the sum for the provided block.
|
97
97
|
# aggregable.sum(&:likes)
|
98
98
|
#
|
99
|
-
# @param [ Symbol ] field The field to sum
|
99
|
+
# @param [ Symbol | Numeric ] field The field to sum, or the initial
|
100
|
+
# value of the sum when a block is given.
|
100
101
|
#
|
101
102
|
# @return [ Float ] The sum value.
|
102
103
|
def sum(field = nil)
|
103
|
-
|
104
|
+
return super(field || 0) if block_given?
|
105
|
+
|
106
|
+
aggregates(field)["sum"] || 0
|
104
107
|
end
|
105
108
|
|
106
109
|
private
|
@@ -169,12 +169,12 @@ module Mongoid
|
|
169
169
|
args.size > 1 || !args.first.is_a?(Hash) && args.first.resizable?
|
170
170
|
end
|
171
171
|
|
172
|
-
# Convenience method of raising an invalid
|
172
|
+
# Convenience method of raising an invalid find error.
|
173
173
|
#
|
174
174
|
# @example Raise the error.
|
175
175
|
# criteria.raise_invalid
|
176
176
|
#
|
177
|
-
# @raise [ Errors::
|
177
|
+
# @raise [ Errors::InvalidFind ] The error.
|
178
178
|
def raise_invalid
|
179
179
|
raise Errors::InvalidFind.new
|
180
180
|
end
|
@@ -44,7 +44,21 @@ module Mongoid
|
|
44
44
|
#
|
45
45
|
# @return [ Object ] The converted number.
|
46
46
|
def __numeric__(object)
|
47
|
-
|
47
|
+
str = object.to_s
|
48
|
+
raise ArgumentError if str.empty?
|
49
|
+
|
50
|
+
# These requirements seem a bit odd, but they're explicitly specified in the tests,
|
51
|
+
# so we're obligated to keep them, for now. (This code was rewritten from a one-line
|
52
|
+
# regex, due to security concerns with a polynomial regex being used on uncontrolled
|
53
|
+
# data).
|
54
|
+
|
55
|
+
str = str.chop if str.end_with?('.')
|
56
|
+
return 0 if str.empty?
|
57
|
+
|
58
|
+
result = Integer(str) rescue Float(object)
|
59
|
+
|
60
|
+
integer = result.to_i
|
61
|
+
integer == result ? integer : result
|
48
62
|
end
|
49
63
|
|
50
64
|
# Evolve the object to an integer.
|
data/lib/mongoid/document.rb
CHANGED
@@ -17,6 +17,7 @@ require 'mongoid/timestamps'
|
|
17
17
|
require 'mongoid/association'
|
18
18
|
require 'mongoid/composable'
|
19
19
|
require 'mongoid/touchable'
|
20
|
+
require 'mongoid/model_resolver'
|
20
21
|
|
21
22
|
module Mongoid
|
22
23
|
# This is the base module for all domain objects that need to be persisted to
|
@@ -31,6 +32,7 @@ module Mongoid
|
|
31
32
|
|
32
33
|
included do
|
33
34
|
Mongoid.register_model(self)
|
35
|
+
Mongoid::ModelResolver.register(self)
|
34
36
|
end
|
35
37
|
|
36
38
|
# Regex for matching illegal BSON keys.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Errors
|
5
|
+
# This error is raised when an around callback is
|
6
|
+
# defined by the user without a yield
|
7
|
+
class InvalidAroundCallback < MongoidError
|
8
|
+
# Create the new error.
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
def initialize
|
12
|
+
super(compose_message('invalid_around_callback'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|