mongoid 9.0.0 → 9.0.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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/Rakefile +44 -21
- data/lib/config/locales/en.yml +4 -0
- data/lib/mongoid/atomic_update_preparer.rb +7 -6
- 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/errors/invalid_around_callback.rb +16 -0
- data/lib/mongoid/errors.rb +1 -0
- data/lib/mongoid/fields.rb +13 -7
- data/lib/mongoid/interceptable.rb +18 -13
- data/lib/mongoid/scopable.rb +7 -1
- data/lib/mongoid/touchable.rb +1 -7
- data/lib/mongoid/version.rb +1 -1
- data/spec/mongoid/association_spec.rb +14 -0
- data/spec/mongoid/attributes_spec.rb +16 -0
- 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/scopable_spec.rb +88 -85
- 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 +8 -80
- 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: f756ccb6822c09519cb0e833a2d3bd2edf5b5a0abf3f3c29205a756682e5d954
|
4
|
+
data.tar.gz: 7d44016955b7e2e90d2dc07b2142cc6c79bacfb83831705f26fdafc773e17e7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e69bc7c2b6031330346265b5c6cdc8d11909fd1204e32727845e3220c6f105dde407006635f31491df9857597711f610a688818dfaa3bc32f27525e2574ce29d
|
7
|
+
data.tar.gz: 259996128cd10553af4972c6b40f5a8ac537158eeaa1cd012bbc9e6d90d67ad745def51fbd47bafaffe9330324967695e45787732446b305d5bdd13338b94075
|
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.
|
@@ -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
|
|
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.
|
@@ -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
|
data/lib/mongoid/errors.rb
CHANGED
@@ -13,6 +13,7 @@ require "mongoid/errors/empty_config_file"
|
|
13
13
|
require "mongoid/errors/immutable_attribute"
|
14
14
|
require "mongoid/errors/in_memory_collation_not_supported"
|
15
15
|
require "mongoid/errors/invalid_auto_encryption_configuration"
|
16
|
+
require "mongoid/errors/invalid_around_callback"
|
16
17
|
require "mongoid/errors/invalid_async_query_executor"
|
17
18
|
require "mongoid/errors/invalid_collection"
|
18
19
|
require "mongoid/errors/invalid_config_file"
|
data/lib/mongoid/fields.rb
CHANGED
@@ -49,6 +49,11 @@ module Mongoid
|
|
49
49
|
# @api private
|
50
50
|
INVALID_BSON_CLASSES = [ BSON::Decimal128, BSON::Int32, BSON::Int64 ].freeze
|
51
51
|
|
52
|
+
# The suffix for generated translated fields.
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
TRANSLATIONS_SFX = '_translations'
|
56
|
+
|
52
57
|
module ClassMethods
|
53
58
|
# Returns the list of id fields for this model class, as both strings
|
54
59
|
# and symbols.
|
@@ -101,8 +106,8 @@ module Mongoid
|
|
101
106
|
ar.each_with_index do |fn, i|
|
102
107
|
key = fn
|
103
108
|
unless klass.fields.key?(fn) || klass.relations.key?(fn)
|
104
|
-
if
|
105
|
-
key =
|
109
|
+
if fn.end_with?(TRANSLATIONS_SFX)
|
110
|
+
key = fn.delete_suffix(TRANSLATIONS_SFX)
|
106
111
|
else
|
107
112
|
key = fn
|
108
113
|
end
|
@@ -408,7 +413,8 @@ module Mongoid
|
|
408
413
|
#
|
409
414
|
# @api private
|
410
415
|
def database_field_name(name, relations, aliased_fields, aliased_associations)
|
411
|
-
return
|
416
|
+
return "" unless name.present?
|
417
|
+
|
412
418
|
key = name.to_s
|
413
419
|
segment, remaining = key.split('.', 2)
|
414
420
|
|
@@ -725,11 +731,11 @@ module Mongoid
|
|
725
731
|
# @api private
|
726
732
|
def create_translations_getter(name, meth)
|
727
733
|
generated_methods.module_eval do
|
728
|
-
re_define_method("#{meth}
|
734
|
+
re_define_method("#{meth}#{TRANSLATIONS_SFX}") do
|
729
735
|
attributes[name] ||= {}
|
730
736
|
attributes[name].with_indifferent_access
|
731
737
|
end
|
732
|
-
alias_method :"#{meth}_t", :"#{meth}
|
738
|
+
alias_method :"#{meth}_t", :"#{meth}#{TRANSLATIONS_SFX}"
|
733
739
|
end
|
734
740
|
end
|
735
741
|
|
@@ -745,14 +751,14 @@ module Mongoid
|
|
745
751
|
# @api private
|
746
752
|
def create_translations_setter(name, meth, field)
|
747
753
|
generated_methods.module_eval do
|
748
|
-
re_define_method("#{meth}
|
754
|
+
re_define_method("#{meth}#{TRANSLATIONS_SFX}=") do |value|
|
749
755
|
attribute_will_change!(name)
|
750
756
|
value&.transform_values! do |_value|
|
751
757
|
field.type.mongoize(_value)
|
752
758
|
end
|
753
759
|
attributes[name] = value
|
754
760
|
end
|
755
|
-
alias_method :"#{meth}_t=", :"#{meth}
|
761
|
+
alias_method :"#{meth}_t=", :"#{meth}#{TRANSLATIONS_SFX}="
|
756
762
|
end
|
757
763
|
end
|
758
764
|
|
@@ -161,11 +161,6 @@ module Mongoid
|
|
161
161
|
# Execute the callbacks of given kind for embedded documents including
|
162
162
|
# around callbacks.
|
163
163
|
#
|
164
|
-
# @note This method is prone to stack overflow errors if the document
|
165
|
-
# has a large number of embedded documents. It is recommended to avoid
|
166
|
-
# using around callbacks for embedded documents until a proper solution
|
167
|
-
# is implemented.
|
168
|
-
#
|
169
164
|
# @param [ Symbol ] kind The type of callback to execute.
|
170
165
|
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
171
166
|
# nil, callbacks will be executed on all cascadable children of
|
@@ -173,17 +168,27 @@ module Mongoid
|
|
173
168
|
#
|
174
169
|
# @api private
|
175
170
|
def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block)
|
176
|
-
|
171
|
+
children = (children || cascadable_children(kind))
|
177
172
|
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
173
|
+
|
174
|
+
return block&.call if children.empty?
|
175
|
+
|
176
|
+
fibers = children.map do |child|
|
177
|
+
Fiber.new do
|
178
|
+
child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
|
179
|
+
Fiber.yield
|
180
|
+
end
|
185
181
|
end
|
186
182
|
end
|
183
|
+
|
184
|
+
fibers.each do |fiber|
|
185
|
+
fiber.resume
|
186
|
+
raise Mongoid::Errors::InvalidAroundCallback unless fiber.alive?
|
187
|
+
end
|
188
|
+
|
189
|
+
block&.call
|
190
|
+
|
191
|
+
fibers.reverse.each(&:resume)
|
187
192
|
end
|
188
193
|
|
189
194
|
# Execute the callbacks of given kind for embedded documents without
|
data/lib/mongoid/scopable.rb
CHANGED
@@ -294,7 +294,13 @@ module Mongoid
|
|
294
294
|
scope = instance_exec(*args, **kwargs, &scoping[:scope])
|
295
295
|
extension = scoping[:extension]
|
296
296
|
to_merge = scope || queryable
|
297
|
-
|
297
|
+
|
298
|
+
criteria = if Mongoid.allow_scopes_to_unset_default_scope
|
299
|
+
to_merge
|
300
|
+
else
|
301
|
+
to_merge.empty_and_chainable? ? to_merge : with_default_scope.merge(to_merge)
|
302
|
+
end
|
303
|
+
|
298
304
|
criteria.extend(extension)
|
299
305
|
criteria
|
300
306
|
end
|
data/lib/mongoid/touchable.rb
CHANGED
@@ -78,7 +78,7 @@ module Mongoid
|
|
78
78
|
field = database_field_name(field)
|
79
79
|
|
80
80
|
write_attribute(:updated_at, now) if respond_to?("updated_at=")
|
81
|
-
write_attribute(field, now) if field
|
81
|
+
write_attribute(field, now) if field.present?
|
82
82
|
|
83
83
|
touches = _extract_touches_from_atomic_sets(field) || {}
|
84
84
|
touches.merge!(_parent._gather_touch_updates(now) || {}) if _touchable_parent?
|
@@ -212,12 +212,6 @@ module Mongoid
|
|
212
212
|
#
|
213
213
|
# @return [ Symbol ] The method name.
|
214
214
|
def define_relation_touch_method(name, association)
|
215
|
-
relation_classes = if association.polymorphic?
|
216
|
-
association.send(:inverse_association_classes)
|
217
|
-
else
|
218
|
-
[ association.relation_class ]
|
219
|
-
end
|
220
|
-
|
221
215
|
method_name = "touch_#{name}_after_create_or_destroy"
|
222
216
|
association.inverse_class.class_eval do
|
223
217
|
define_method(method_name) do
|
data/lib/mongoid/version.rb
CHANGED
@@ -15,6 +15,20 @@ describe Mongoid::Association do
|
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
18
|
+
context "when class_name references an unknown class" do
|
19
|
+
context "when loading" do
|
20
|
+
it "does not raise an exception" do
|
21
|
+
expect do
|
22
|
+
class AssocationSpecModel
|
23
|
+
include Mongoid::Document
|
24
|
+
|
25
|
+
embedded_in :parent, class_name: 'SomethingBogusThatDoesNotExistYet'
|
26
|
+
end
|
27
|
+
end.not_to raise_exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
18
32
|
describe "#embedded?" do
|
19
33
|
|
20
34
|
let(:person) do
|
@@ -289,6 +289,22 @@ describe Mongoid::Attributes do
|
|
289
289
|
end
|
290
290
|
end
|
291
291
|
|
292
|
+
context "when given nil" do
|
293
|
+
|
294
|
+
it "returns nil" do
|
295
|
+
expect(person[nil]).to be nil
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
context "when given an empty string" do
|
301
|
+
|
302
|
+
it "returns nil" do
|
303
|
+
expect(person[""]).to be nil
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
292
308
|
context "when the field was not explicitly defined" do
|
293
309
|
|
294
310
|
context "when excluding with only and the field was not excluded" do
|
@@ -570,5 +570,16 @@ describe Mongoid::Contextual::Aggregable::Memory do
|
|
570
570
|
expect(sum).to eq(1500)
|
571
571
|
end
|
572
572
|
end
|
573
|
+
|
574
|
+
context "when provided a block with initial value" do
|
575
|
+
|
576
|
+
let(:sum) do
|
577
|
+
context.sum(500, &:likes)
|
578
|
+
end
|
579
|
+
|
580
|
+
it "returns the sum for the provided block starting from initial value" do
|
581
|
+
expect(sum).to eq(2000)
|
582
|
+
end
|
583
|
+
end
|
573
584
|
end
|
574
585
|
end
|
@@ -515,6 +515,17 @@ describe Mongoid::Contextual::Aggregable::Mongo do
|
|
515
515
|
expect(sum).to eq(1500)
|
516
516
|
end
|
517
517
|
end
|
518
|
+
|
519
|
+
context "when provided a block with initial value" do
|
520
|
+
|
521
|
+
let(:sum) do
|
522
|
+
context.sum(500, &:likes)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "returns the sum for the provided block starting from initial value" do
|
526
|
+
expect(sum).to eq(2000)
|
527
|
+
end
|
528
|
+
end
|
518
529
|
end
|
519
530
|
end
|
520
531
|
|
@@ -3640,6 +3640,75 @@ describe Mongoid::Contextual::Mongo do
|
|
3640
3640
|
expect(new_order.reload.genres).to eq(["electronic"])
|
3641
3641
|
end
|
3642
3642
|
end
|
3643
|
+
|
3644
|
+
context "when operation is $pull" do
|
3645
|
+
context "when pulling single element" do
|
3646
|
+
|
3647
|
+
before do
|
3648
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop"])
|
3649
|
+
new_order.update_attribute(:genres, ["electronic", "pop"])
|
3650
|
+
context.update_all("$pull" => { genres: "electronic" })
|
3651
|
+
end
|
3652
|
+
|
3653
|
+
it "updates the first matching document" do
|
3654
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3655
|
+
end
|
3656
|
+
|
3657
|
+
it "updates the last matching document" do
|
3658
|
+
expect(new_order.reload.genres).to eq(["pop"])
|
3659
|
+
end
|
3660
|
+
end
|
3661
|
+
|
3662
|
+
context "when pulling based on condition" do
|
3663
|
+
before do
|
3664
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3665
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3666
|
+
context.update_all("$pull" => { genres: { '$in' => ["electronic", "pop"] } })
|
3667
|
+
end
|
3668
|
+
|
3669
|
+
it "updates the first matching document" do
|
3670
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3671
|
+
end
|
3672
|
+
|
3673
|
+
it "updates the last matching document" do
|
3674
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3675
|
+
end
|
3676
|
+
end
|
3677
|
+
end
|
3678
|
+
|
3679
|
+
context "when operation is $pop" do
|
3680
|
+
|
3681
|
+
before do
|
3682
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic"])
|
3683
|
+
end
|
3684
|
+
|
3685
|
+
it "removes first element in array" do
|
3686
|
+
context.update_all("$pop" => { genres: -1 })
|
3687
|
+
expect(depeche_mode.reload.genres).to eq(["electronic"])
|
3688
|
+
end
|
3689
|
+
|
3690
|
+
it "removes last element in array" do
|
3691
|
+
context.update_all("$pop" => { genres: 1 })
|
3692
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3693
|
+
end
|
3694
|
+
end
|
3695
|
+
|
3696
|
+
context "when operation is $pullAll" do
|
3697
|
+
|
3698
|
+
before do
|
3699
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic", "dance", "pop" ])
|
3700
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "electronic", "dance"])
|
3701
|
+
context.update_all("$pullAll" => { genres: ["pop", "electronic"] })
|
3702
|
+
end
|
3703
|
+
|
3704
|
+
it "updates the first matching document" do
|
3705
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3706
|
+
end
|
3707
|
+
|
3708
|
+
it "updates the last matching document" do
|
3709
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3710
|
+
end
|
3711
|
+
end
|
3643
3712
|
end
|
3644
3713
|
|
3645
3714
|
context 'when using aliased field names' do
|
@@ -3659,15 +3728,15 @@ describe Mongoid::Contextual::Mongo do
|
|
3659
3728
|
context "when the attributes must be mongoized" do
|
3660
3729
|
|
3661
3730
|
before do
|
3662
|
-
context.update_all("$set" => {
|
3731
|
+
context.update_all("$set" => { location: LatLng.new(52.30, 13.25) })
|
3663
3732
|
end
|
3664
3733
|
|
3665
3734
|
it "updates the first matching document" do
|
3666
|
-
expect(depeche_mode.reload.
|
3735
|
+
expect(depeche_mode.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3667
3736
|
end
|
3668
3737
|
|
3669
3738
|
it "updates the last matching document" do
|
3670
|
-
expect(new_order.reload.
|
3739
|
+
expect(new_order.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3671
3740
|
end
|
3672
3741
|
end
|
3673
3742
|
end
|
data/spec/mongoid/fields_spec.rb
CHANGED
@@ -1871,12 +1871,12 @@ describe Mongoid::Fields do
|
|
1871
1871
|
|
1872
1872
|
context 'given nil' do
|
1873
1873
|
subject { Person.database_field_name(nil) }
|
1874
|
-
it { is_expected.to eq
|
1874
|
+
it { is_expected.to eq '' }
|
1875
1875
|
end
|
1876
1876
|
|
1877
1877
|
context 'given an empty String' do
|
1878
1878
|
subject { Person.database_field_name('') }
|
1879
|
-
it { is_expected.to eq
|
1879
|
+
it { is_expected.to eq '' }
|
1880
1880
|
end
|
1881
1881
|
|
1882
1882
|
context 'given a String' do
|