mongoid 9.0.0 → 9.0.2
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
- 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
|