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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4218c578b31195178d4f2425bf42c70741f23e123832c9dcc0df9794b1bfbaa
4
- data.tar.gz: 24b7b07e571fff97c9c35cc4f2477f6def8202211a35fb205711f73492f8f68c
3
+ metadata.gz: 8f349e627130f8eacea25a6242dbcb2d3c48e8c75c7740368afeb62e5939f7c3
4
+ data.tar.gz: 1acc6e8d45a07d5d6a140228804eb6f9cdb6b89ac8deeb39283c89338dbbf256
5
5
  SHA512:
6
- metadata.gz: 4086af26408203774f2c4861ae84707adea2dd45fff821470a9517e9ec10c41fc4c80a3e566a25118806e2d89311f6eb1aa8a9e27953ba5784cb22d78025e0ea
7
- data.tar.gz: 1b50e4fff002cc80175aa6c8e489f79c37f5b2cfebdf9adfe6da316b38bab18540a96717d7f217ed2054f7022faf4ec9eb42129e0474b59d3266c3585d237184
6
+ metadata.gz: 418c4bf1aac91a436d7d149b5961273c4f704b122d554f76dbe42ff6a29a777e5a3c7dc97c80900c3341cdaabc4e1536e883c00c283fd040cea05b352b2a0a5a
7
+ data.tar.gz: 65371b0d3a22ecbeeecae3a9091bc9540921155debff4b556419280bd5c76a3205125e9bb3bb781490031564f7a532dbebe68f72c5ba3c7542690ef3f5308173
data/Rakefile CHANGED
@@ -55,7 +55,7 @@ task :release do
55
55
  WARNING
56
56
  end
57
57
 
58
- system 'gem', 'push', "mongoid-#{Mongoid::VERSION}.gem"
58
+ system 'bundle', 'exec', 'gem', 'push', "mongoid-#{Mongoid::VERSION}.gem"
59
59
  end
60
60
 
61
61
  RSpec::Core::RakeTask.new("spec") do |spec|
@@ -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 = true }
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)
@@ -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
- BSON::Document.new(as_attributes)
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.
@@ -17,6 +17,7 @@ module Mongoid
17
17
  #
18
18
  # @return [ Integer ] -1, 0, 1.
19
19
  def <=>(other)
20
+ return super unless other.is_a?(Mongoid::Equality)
20
21
  attributes["_id"].to_s <=> other.attributes["_id"].to_s
21
22
  end
22
23
 
@@ -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.
@@ -12,13 +12,13 @@ module Mongoid
12
12
  included do
13
13
 
14
14
  class << self
15
- # Note that this intentionally only delegates :include_root_in_json
16
- # and not :include_root_in_json? - delegating the latter produces
17
- # wrong behavior.
18
- # Also note that this intentionally uses the ActiveSupport delegation
19
- # functionality and not the Ruby standard library one.
20
- # See https://jira.mongodb.org/browse/MONGOID-4849.
21
- delegate :include_root_in_json, to: ::Mongoid
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
 
@@ -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
- super
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
- list.all? do |value|
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mongoid
4
- VERSION = "8.1.6"
4
+ VERSION = "8.1.8"
5
5
  end
@@ -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(:description) do
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 << description
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(description).to_not be_valid
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.6
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: 2024-09-20 00:00:00.000000000 Z
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: '7.3'
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: '7.3'
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.4.19
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: