mongoid 8.1.6 → 8.1.8
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/Rakefile +1 -1
- data/lib/mongoid/attributes/readonly.rb +8 -3
- data/lib/mongoid/criteria/queryable/selectable.rb +1 -1
- data/lib/mongoid/document.rb +8 -1
- data/lib/mongoid/equality.rb +1 -0
- data/lib/mongoid/matcher.rb +15 -1
- data/lib/mongoid/serializable.rb +7 -7
- data/lib/mongoid/traversable.rb +24 -1
- data/lib/mongoid/validatable/associated.rb +5 -2
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/app_spec.rb +11 -3
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +4 -0
- data/spec/mongoid/attributes/readonly_spec.rb +19 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +29 -0
- data/spec/mongoid/document_spec.rb +27 -0
- data/spec/mongoid/equality_spec.rb +6 -0
- data/spec/mongoid/validatable/associated_spec.rb +14 -4
- metadata +5 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f349e627130f8eacea25a6242dbcb2d3c48e8c75c7740368afeb62e5939f7c3
|
4
|
+
data.tar.gz: 1acc6e8d45a07d5d6a140228804eb6f9cdb6b89ac8deeb39283c89338dbbf256
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 418c4bf1aac91a436d7d149b5961273c4f704b122d554f76dbe42ff6a29a777e5a3c7dc97c80900c3341cdaabc4e1536e883c00c283fd040cea05b352b2a0a5a
|
7
|
+
data.tar.gz: 65371b0d3a22ecbeeecae3a9091bc9540921155debff4b556419280bd5c76a3205125e9bb3bb781490031564f7a532dbebe68f72c5ba3c7542690ef3f5308173
|
data/Rakefile
CHANGED
@@ -22,7 +22,7 @@ module Mongoid
|
|
22
22
|
# @return [ true | false ] If the document is new, or if the field is not
|
23
23
|
# readonly.
|
24
24
|
def attribute_writable?(name)
|
25
|
-
new_record? || (!readonly_attributes.include?(name) && _loaded?(name))
|
25
|
+
new_record? || (!self.class.readonly_attributes.include?(name) && _loaded?(name))
|
26
26
|
end
|
27
27
|
|
28
28
|
private
|
@@ -62,12 +62,17 @@ module Mongoid
|
|
62
62
|
# end
|
63
63
|
#
|
64
64
|
# @param [ Symbol... ] *names The names of the fields.
|
65
|
+
# @note When a parent class contains readonly attributes and is then
|
66
|
+
# inherited by a child class, the child class will inherit the
|
67
|
+
# parent's readonly attributes at the time of its creation.
|
68
|
+
# Updating the parent does not propagate down to child classes after wards.
|
65
69
|
def attr_readonly(*names)
|
70
|
+
self.readonly_attributes = self.readonly_attributes.dup
|
66
71
|
names.each do |name|
|
67
|
-
readonly_attributes << database_field_name(name)
|
72
|
+
self.readonly_attributes << database_field_name(name)
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
73
|
-
end
|
78
|
+
end
|
@@ -552,7 +552,7 @@ module Mongoid
|
|
552
552
|
# @return [ Selectable ] The new selectable.
|
553
553
|
def not(*criteria)
|
554
554
|
if criteria.empty?
|
555
|
-
dup.tap { |query| query.negating =
|
555
|
+
dup.tap { |query| query.negating = !query.negating }
|
556
556
|
else
|
557
557
|
criteria.compact.inject(self.clone) do |c, new_s|
|
558
558
|
if new_s.is_a?(Selectable)
|
data/lib/mongoid/document.rb
CHANGED
@@ -133,7 +133,14 @@ module Mongoid
|
|
133
133
|
#
|
134
134
|
# @return [ Hash ] A hash of all attributes in the hierarchy.
|
135
135
|
def as_document
|
136
|
-
|
136
|
+
attrs = as_attributes
|
137
|
+
|
138
|
+
# legacy attributes have a tendency to leak internal state via
|
139
|
+
# `as_document`; we have to deep_dup the attributes here to prevent
|
140
|
+
# that.
|
141
|
+
attrs = attrs.deep_dup if Mongoid.legacy_attributes
|
142
|
+
|
143
|
+
BSON::Document.new(attrs)
|
137
144
|
end
|
138
145
|
|
139
146
|
# Calls #as_json on the document with additional, Mongoid-specific options.
|
data/lib/mongoid/equality.rb
CHANGED
data/lib/mongoid/matcher.rb
CHANGED
@@ -35,11 +35,25 @@ module Mongoid
|
|
35
35
|
# from and behaves identically to association traversal for the purposes
|
36
36
|
# of, for example, subsequent array element retrieval.
|
37
37
|
#
|
38
|
-
# @param [ Document | Hash ] document The document to extract from.
|
38
|
+
# @param [ Document | Hash | String ] document The document to extract from.
|
39
39
|
# @param [ String ] key The key path to extract.
|
40
40
|
#
|
41
41
|
# @return [ Object | Array ] Field value or values.
|
42
42
|
module_function def extract_attribute(document, key)
|
43
|
+
# The matcher system will wind up sending atomic values to this as well,
|
44
|
+
# when attepting to match more complex types. If anything other than a
|
45
|
+
# Document or a Hash is given, we'll short-circuit the logic and just
|
46
|
+
# return an empty array.
|
47
|
+
return [] unless document.is_a?(Hash) || document.is_a?(Document)
|
48
|
+
|
49
|
+
# Performance optimization; if the key does not include a '.' character,
|
50
|
+
# it must reference an immediate attribute of the document.
|
51
|
+
unless key.include?('.')
|
52
|
+
hash = document.respond_to?(:attributes) ? document.attributes : document
|
53
|
+
key = find_exact_key(hash, key)
|
54
|
+
return key ? [ hash[key] ] : []
|
55
|
+
end
|
56
|
+
|
43
57
|
if document.respond_to?(:as_attributes, true)
|
44
58
|
# If a document has hash fields, as_attributes would keep those fields
|
45
59
|
# as Hash instances which do not offer indifferent access.
|
data/lib/mongoid/serializable.rb
CHANGED
@@ -12,13 +12,13 @@ module Mongoid
|
|
12
12
|
included do
|
13
13
|
|
14
14
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def include_root_in_json
|
16
|
+
@include_root_in_json.nil? ? ::Mongoid.include_root_in_json : @include_root_in_json
|
17
|
+
end
|
18
|
+
|
19
|
+
def include_root_in_json=(new_value)
|
20
|
+
@include_root_in_json = new_value
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/mongoid/traversable.rb
CHANGED
@@ -7,6 +7,29 @@ module Mongoid
|
|
7
7
|
# Provides behavior around traversing the document graph.
|
8
8
|
module Traversable
|
9
9
|
extend ActiveSupport::Concern
|
10
|
+
# This code is extracted from ActiveSupport so that we do not depend on
|
11
|
+
# their private API that may change at any time.
|
12
|
+
# This code should be reviewed and maybe removed when implementing
|
13
|
+
# https://jira.mongodb.org/browse/MONGOID-5832
|
14
|
+
class << self
|
15
|
+
# @api private
|
16
|
+
def __redefine(owner, name, value)
|
17
|
+
if owner.singleton_class?
|
18
|
+
owner.redefine_method(name) { value }
|
19
|
+
owner.send(:public, name)
|
20
|
+
end
|
21
|
+
owner.redefine_singleton_method(name) { value }
|
22
|
+
owner.singleton_class.send(:public, name)
|
23
|
+
owner.redefine_singleton_method("#{name}=") do |new_value|
|
24
|
+
if owner.equal?(self)
|
25
|
+
value = new_value
|
26
|
+
else
|
27
|
+
::Mongoid::Traversable.redefine(self, name, new_value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
owner.singleton_class.send(:public, "#{name}=")
|
31
|
+
end
|
32
|
+
end
|
10
33
|
|
11
34
|
def _parent
|
12
35
|
@__parent ||= nil
|
@@ -30,7 +53,7 @@ module Mongoid
|
|
30
53
|
if value
|
31
54
|
Mongoid::Fields::Validators::Macro.validate_field_name(self, value)
|
32
55
|
value = value.to_s
|
33
|
-
|
56
|
+
::Mongoid::Traversable.__redefine(self, 'discriminator_key', value)
|
34
57
|
else
|
35
58
|
# When discriminator key is set to nil, replace the class's definition
|
36
59
|
# of the discriminator key reader (provided by class_attribute earlier)
|
@@ -69,13 +69,16 @@ module Mongoid
|
|
69
69
|
# Now, treating the target as an array, look at each element
|
70
70
|
# and see if it is valid, but only if it has already been
|
71
71
|
# persisted, or changed, and hasn't been flagged for destroy.
|
72
|
-
|
72
|
+
#
|
73
|
+
# use map.all? instead of just all?, because all? will do short-circuit
|
74
|
+
# evaluation and terminate on the first failed validation.
|
75
|
+
list.map do |value|
|
73
76
|
if value && !value.flagged_for_destroy? && (!value.persisted? || value.changed?)
|
74
77
|
value.validated? ? true : value.valid?
|
75
78
|
else
|
76
79
|
true
|
77
80
|
end
|
78
|
-
end
|
81
|
+
end.all?
|
79
82
|
end
|
80
83
|
|
81
84
|
document.errors.add(attribute, :invalid) unless valid
|
data/lib/mongoid/version.rb
CHANGED
@@ -26,6 +26,8 @@ describe 'Mongoid application tests' do
|
|
26
26
|
context 'demo application' do
|
27
27
|
context 'sinatra' do
|
28
28
|
it 'runs' do
|
29
|
+
skip 'https://jira.mongodb.org/browse/MONGOID-5826'
|
30
|
+
|
29
31
|
clone_application(
|
30
32
|
'https://github.com/mongoid/mongoid-demo',
|
31
33
|
subdir: 'sinatra-minimal',
|
@@ -45,6 +47,8 @@ describe 'Mongoid application tests' do
|
|
45
47
|
|
46
48
|
context 'rails-api' do
|
47
49
|
it 'runs' do
|
50
|
+
skip 'https://jira.mongodb.org/browse/MONGOID-5826'
|
51
|
+
|
48
52
|
clone_application(
|
49
53
|
'https://github.com/mongoid/mongoid-demo',
|
50
54
|
subdir: 'rails-api',
|
@@ -95,7 +99,7 @@ describe 'Mongoid application tests' do
|
|
95
99
|
check_call(%w(rails new mongoid-test --skip-spring --skip-active-record), env: clean_env)
|
96
100
|
|
97
101
|
Dir.chdir('mongoid-test') do
|
98
|
-
adjust_app_gemfile
|
102
|
+
adjust_app_gemfile(add_sprockets: SpecConfig.instance.rails_version != '8.0')
|
99
103
|
check_call(%w(bundle install), env: clean_env)
|
100
104
|
|
101
105
|
check_call(%w(rails g model post), env: clean_env)
|
@@ -117,7 +121,7 @@ describe 'Mongoid application tests' do
|
|
117
121
|
check_call(%w(rails new mongoid-test-config --skip-spring --skip-active-record), env: clean_env)
|
118
122
|
|
119
123
|
Dir.chdir('mongoid-test-config') do
|
120
|
-
adjust_app_gemfile
|
124
|
+
adjust_app_gemfile(add_sprockets: SpecConfig.instance.rails_version != '8.0')
|
121
125
|
check_call(%w(bundle install), env: clean_env)
|
122
126
|
|
123
127
|
mongoid_config_file = File.join(TMP_BASE,'mongoid-test-config/config/mongoid.yml')
|
@@ -139,7 +143,7 @@ describe 'Mongoid application tests' do
|
|
139
143
|
if (rails_version = SpecConfig.instance.rails_version) == 'master'
|
140
144
|
else
|
141
145
|
check_call(%w(gem list))
|
142
|
-
check_call(%w(gem install rails --no-document -v) + ["~> #{rails_version}.0"])
|
146
|
+
check_call(%w(gem install rails --no-document --force -v) + ["~> #{rails_version}.0"])
|
143
147
|
end
|
144
148
|
end
|
145
149
|
|
@@ -287,6 +291,10 @@ describe 'Mongoid application tests' do
|
|
287
291
|
end
|
288
292
|
|
289
293
|
def adjust_rails_defaults(rails_version: SpecConfig.instance.rails_version)
|
294
|
+
if !rails_version.match?(/^\d+\.\d+$/)
|
295
|
+
# This must be pre-release version, we trim it
|
296
|
+
rails_version = rails_version.split('.')[0..1].join('.')
|
297
|
+
end
|
290
298
|
if File.exist?('config/application.rb')
|
291
299
|
lines = IO.readlines('config/application.rb')
|
292
300
|
lines.each do |line|
|
@@ -749,6 +749,10 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
|
|
749
749
|
person.save!
|
750
750
|
end
|
751
751
|
|
752
|
+
# NOTE: there as a bad interdependency here, with the auto_save_spec.rb
|
753
|
+
# file. If auto_save_spec.rb runs before this, the following specs fail
|
754
|
+
# with "undefined method `nullify' for an instance of Person".
|
755
|
+
|
752
756
|
context "when parent exists" do
|
753
757
|
|
754
758
|
context "when child is destroyed" do
|
@@ -265,7 +265,26 @@ describe Mongoid::Attributes::Readonly do
|
|
265
265
|
expect(child.mother).to be_nil
|
266
266
|
end
|
267
267
|
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context "when a subclass inherits readonly fields" do
|
271
|
+
let(:attributes) do
|
272
|
+
[:title, :terms]
|
273
|
+
end
|
274
|
+
|
275
|
+
before do
|
276
|
+
class OldPerson < Person
|
277
|
+
attr_readonly :age
|
278
|
+
end
|
279
|
+
end
|
268
280
|
|
281
|
+
it "ensures subclass inherits the readonly attributes from parent" do
|
282
|
+
expect(OldPerson.readonly_attributes.to_a).to include("title","terms")
|
283
|
+
end
|
284
|
+
|
285
|
+
it "ensures subclass does not modify parent's readonly attributes" do
|
286
|
+
expect(Person.readonly_attributes.to_a).not_to include("age")
|
287
|
+
end
|
269
288
|
end
|
270
289
|
end
|
271
290
|
end
|
@@ -2059,6 +2059,35 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
2059
2059
|
end
|
2060
2060
|
end
|
2061
2061
|
|
2062
|
+
describe "#not" do
|
2063
|
+
context "when negating a criterion" do
|
2064
|
+
let(:selection) do
|
2065
|
+
query.not(field: /value/)
|
2066
|
+
end
|
2067
|
+
|
2068
|
+
it "adds the $not selector" do
|
2069
|
+
expect(selection.selector).to eq({
|
2070
|
+
"field" => { "$not" => /value/ }
|
2071
|
+
})
|
2072
|
+
end
|
2073
|
+
|
2074
|
+
it "returns a cloned query" do
|
2075
|
+
expect(selection).to_not equal(query)
|
2076
|
+
end
|
2077
|
+
|
2078
|
+
context "when toggling negation state" do
|
2079
|
+
it "negates the negating value" do
|
2080
|
+
expect(query.negating).to be_nil
|
2081
|
+
negated_query = query.not
|
2082
|
+
expect(negated_query.negating).to be true
|
2083
|
+
double_negated_query = negated_query.not
|
2084
|
+
expect(double_negated_query.negating).to be false
|
2085
|
+
end
|
2086
|
+
end
|
2087
|
+
end
|
2088
|
+
end
|
2089
|
+
|
2090
|
+
|
2062
2091
|
describe Symbol do
|
2063
2092
|
|
2064
2093
|
describe "#all" do
|
@@ -591,6 +591,33 @@ describe Mongoid::Document do
|
|
591
591
|
expect(person.as_document["addresses"].first).to have_key(:locations)
|
592
592
|
end
|
593
593
|
|
594
|
+
context 'when modifying the returned object' do
|
595
|
+
let(:record) do
|
596
|
+
RootCategory.create(categories: [{ name: 'tests' }]).reload
|
597
|
+
end
|
598
|
+
|
599
|
+
shared_examples_for 'an object with protected internal state' do
|
600
|
+
it 'does not expose internal state' do
|
601
|
+
before_change = record.as_document.dup
|
602
|
+
record.categories.first.name = 'things'
|
603
|
+
after_change = record.as_document
|
604
|
+
expect(before_change['categories'].first['name']).not_to eq('things')
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
context 'when legacy_attributes is true' do
|
609
|
+
config_override :legacy_attributes, true
|
610
|
+
|
611
|
+
it_behaves_like 'an object with protected internal state'
|
612
|
+
end
|
613
|
+
|
614
|
+
context 'when legacy_attributes is false' do
|
615
|
+
config_override :legacy_attributes, false
|
616
|
+
|
617
|
+
it_behaves_like 'an object with protected internal state'
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
594
621
|
context "with relation define store_as option in embeded_many" do
|
595
622
|
|
596
623
|
let!(:phone) do
|
@@ -291,6 +291,12 @@ describe Mongoid::Equality do
|
|
291
291
|
it "compares based on the document id" do
|
292
292
|
expect(first <=> second).to eq(-1)
|
293
293
|
end
|
294
|
+
|
295
|
+
it "doesn't break if one isn't a document" do
|
296
|
+
expect do
|
297
|
+
first <=> "Foo"
|
298
|
+
end.to_not raise_error
|
299
|
+
end
|
294
300
|
end
|
295
301
|
|
296
302
|
describe "#eql?" do
|
@@ -37,12 +37,18 @@ describe Mongoid::Validatable::AssociatedValidator do
|
|
37
37
|
User.new(name: "test")
|
38
38
|
end
|
39
39
|
|
40
|
-
let(:
|
40
|
+
let(:description1) do
|
41
|
+
Description.new
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:description2) do
|
41
45
|
Description.new
|
42
46
|
end
|
43
47
|
|
44
48
|
before do
|
45
|
-
user.descriptions <<
|
49
|
+
user.descriptions << description1
|
50
|
+
user.descriptions << description2
|
51
|
+
user.valid?
|
46
52
|
end
|
47
53
|
|
48
54
|
it "only validates the parent once" do
|
@@ -50,12 +56,16 @@ describe Mongoid::Validatable::AssociatedValidator do
|
|
50
56
|
end
|
51
57
|
|
52
58
|
it "adds the errors from the relation" do
|
53
|
-
user.valid?
|
54
59
|
expect(user.errors[:descriptions]).to_not be_nil
|
55
60
|
end
|
56
61
|
|
62
|
+
it 'reports all failed validations' do
|
63
|
+
errors = user.descriptions.flat_map { |d| d.errors[:details] }
|
64
|
+
expect(errors.length).to be == 2
|
65
|
+
end
|
66
|
+
|
57
67
|
it "only validates the child once" do
|
58
|
-
expect(
|
68
|
+
expect(description1).to_not be_valid
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.1.
|
4
|
+
version: 8.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The MongoDB Ruby Team
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-07 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: activemodel
|
@@ -19,7 +18,7 @@ dependencies:
|
|
19
18
|
version: '5.1'
|
20
19
|
- - "<"
|
21
20
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
21
|
+
version: '8.1'
|
23
22
|
- - "!="
|
24
23
|
- !ruby/object:Gem::Version
|
25
24
|
version: 7.0.0
|
@@ -32,7 +31,7 @@ dependencies:
|
|
32
31
|
version: '5.1'
|
33
32
|
- - "<"
|
34
33
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
34
|
+
version: '8.1'
|
36
35
|
- - "!="
|
37
36
|
- !ruby/object:Gem::Version
|
38
37
|
version: 7.0.0
|
@@ -1146,7 +1145,6 @@ metadata:
|
|
1146
1145
|
documentation_uri: https://www.mongodb.com/docs/mongoid/
|
1147
1146
|
homepage_uri: https://mongoid.org/
|
1148
1147
|
source_code_uri: https://github.com/mongodb/mongoid
|
1149
|
-
post_install_message:
|
1150
1148
|
rdoc_options: []
|
1151
1149
|
require_paths:
|
1152
1150
|
- lib
|
@@ -1161,8 +1159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1161
1159
|
- !ruby/object:Gem::Version
|
1162
1160
|
version: 1.3.6
|
1163
1161
|
requirements: []
|
1164
|
-
rubygems_version: 3.
|
1165
|
-
signing_key:
|
1162
|
+
rubygems_version: 3.6.2
|
1166
1163
|
specification_version: 4
|
1167
1164
|
summary: Elegant Persistence in Ruby for MongoDB.
|
1168
1165
|
test_files:
|