Skip to content

Commit 009e104

Browse files
committed
Merge remote-tracking branch 'remotes/origin/master' into docs-full-namespaces
2 parents 1eaabc2 + 9892a68 commit 009e104

File tree

27 files changed

+863
-246
lines changed

27 files changed

+863
-246
lines changed

.evergreen/config.yml

+12-13
Original file line numberDiff line numberDiff line change
@@ -763,16 +763,15 @@ buildvariants:
763763
tasks:
764764
- name: "test"
765765

766-
# https://jira.mongodb.org/browse/MONGOID-5549
767-
# - matrix_name: app-tests-jruby
768-
# matrix_spec:
769-
# jruby: ["jruby-9.3"]
770-
# driver: ["current"]
771-
# mongodb-version: '5.0'
772-
# topology: standalone
773-
# app-tests: yes
774-
# rails: ['6.0']
775-
# os: ubuntu-18.04
776-
# display_name: "app tests ${driver}, ${jruby}"
777-
# tasks:
778-
# - name: "test"
766+
- matrix_name: app-tests-jruby
767+
matrix_spec:
768+
jruby: ["jruby-9.3"]
769+
driver: ["current"]
770+
mongodb-version: '5.0'
771+
topology: standalone
772+
app-tests: yes
773+
rails: ['6.0']
774+
os: ubuntu-18.04
775+
display_name: "app tests ${driver}, ${jruby}"
776+
tasks:
777+
- name: "test"

.github/workflows/test.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ jobs:
138138
i18n:
139139
gemfile: gemfiles/rails-6.0.gemfile
140140
experimental: false
141-
142141
- mongodb: '5.0'
143142
ruby: ruby-3.1
144143
topology: replica_set
@@ -162,7 +161,7 @@ jobs:
162161
- mongodb: '4.0'
163162
ruby: ruby-2.7
164163
topology: replica_set
165-
os: ubuntu-18.04
164+
os: ubuntu-20.04
166165
task: test
167166
driver: current
168167
rails:
@@ -172,15 +171,14 @@ jobs:
172171
- mongodb: '3.6'
173172
ruby: ruby-2.7
174173
topology: replica_set
175-
os: ubuntu-18.04
174+
os: ubuntu-20.04
176175
task: test
177176
driver: current
178177
rails:
179178
i18n:
180179
gemfile: Gemfile
181180
experimental: false
182181

183-
184182
steps:
185183
- name: repo checkout
186184
uses: actions/checkout@v2

docs/reference/indexes.txt

+19
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,25 @@ Indexes can be scoped to a specific database:
8282
index({ ssn: 1 }, { database: "users", unique: true, background: true })
8383
end
8484

85+
You may use aliased field names in index definitions. Field aliases
86+
will also be resolved on the following options: ``partial_filter_expression``,
87+
``weights``, ``wildcard_projection``.
88+
89+
.. code-block:: ruby
90+
91+
class Person
92+
include Mongoid::Document
93+
field :a, as: :age
94+
index({ age: 1 }, { partial_filter_expression: { age: { '$gte' => 20 } })
95+
end
96+
97+
.. note::
98+
99+
The expansion of field name aliases in index options such as
100+
``partial_filter_expression`` is performed according to the behavior of MongoDB
101+
server 6.0. Future server versions may change how they interpret these options,
102+
and Mongoid's functionality may not support such changes.
103+
85104
Mongoid can define indexes on "foreign key" fields for associations.
86105
This only works on the association macro that the foreign key is stored on:
87106

docs/release-notes/mongoid-9.0.txt

+23
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,29 @@ defaults to ``true``.
241241
When set to false, the older, inconsistent behavior is restored.
242242

243243

244+
Support Field Aliases on Index Options
245+
--------------------------------------
246+
247+
Support has been added to use aliased field names in the following options
248+
of the ``index`` macro: ``partial_filter_expression``, ``weights``,
249+
``wildcard_projection``.
250+
251+
.. code-block:: ruby
252+
253+
class Person
254+
include Mongoid::Document
255+
field :a, as: :age
256+
index({ age: 1 }, { partial_filter_expression: { age: { '$gte' => 20 } })
257+
end
258+
259+
.. note::
260+
261+
The expansion of field name aliases in index options such as
262+
``partial_filter_expression`` is performed according to the behavior of MongoDB
263+
server 6.0. Future server versions may change how they interpret these options,
264+
and Mongoid's functionality may not support such changes.
265+
266+
244267
Bug Fixes and Improvements
245268
--------------------------
246269

lib/mongoid/association/eager.rb

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# frozen_string_literal: true
2+
3+
module Mongoid
4+
module Association
5+
6+
# Base class for eager load preload functions.
7+
class Eager
8+
# Instantiate the eager load class.
9+
#
10+
# @example Create the new belongs to eager load preloader.
11+
# BelongsTo.new(association, parent_docs)
12+
#
13+
# @param [ Array<Mongoid::Association::Relatable> ] associations
14+
# Associations to eager load
15+
# @param [ Array<Document> ] docs Documents to preload the associations
16+
#
17+
# @return [ Base ] The eager load preloader
18+
def initialize(associations, docs)
19+
@associations = associations
20+
@docs = docs
21+
@grouped_docs = {}
22+
end
23+
24+
# Run the preloader.
25+
#
26+
# @example Preload the associations into the documents.
27+
# loader.run
28+
#
29+
# @return [ Array ] The list of documents given.
30+
def run
31+
@loaded = []
32+
while shift_association
33+
preload
34+
@loaded << @docs.collect { |d| d.send(@association.name) if d.respond_to?(@association.name) }
35+
end
36+
@loaded.flatten
37+
end
38+
39+
protected
40+
41+
# Preload the current association.
42+
#
43+
# This method should be implemented in the subclass
44+
#
45+
# @example Preload the current association into the documents.
46+
# loader.preload
47+
def preload
48+
raise NotImplementedError
49+
end
50+
51+
# Retrieves the documents referenced by the association, and
52+
# yields each one sequentially to the provided block. If the
53+
# association is not polymorphic, all documents are retrieved in
54+
# a single query. If the association is polymorphic, one query is
55+
# issued per association target class.
56+
def each_loaded_document(&block)
57+
each_loaded_document_of_class(@association.klass, keys_from_docs, &block)
58+
end
59+
60+
# Retrieves the documents of the specified class, that have the
61+
# foreign key included in the specified list of keys.
62+
#
63+
# When the documents are retrieved, the set of inclusions applied
64+
# is the set of inclusions applied to the host document minus the
65+
# association that is being eagerly loaded.
66+
private def each_loaded_document_of_class(cls, keys)
67+
# Note: keys should not include nil elements.
68+
# Upstream code is responsible for eliminating nils from keys.
69+
return cls.none if keys.empty?
70+
71+
criteria = cls.criteria
72+
criteria = criteria.apply_scope(@association.scope)
73+
criteria = criteria.any_in(key => keys)
74+
criteria.inclusions = criteria.inclusions - [@association]
75+
criteria.each do |doc|
76+
yield doc
77+
end
78+
end
79+
80+
# Set the pre-loaded document into its parent.
81+
#
82+
# @example Set docs into parent with pk = "foo"
83+
# loader.set_on_parent("foo", docs)
84+
#
85+
# @param [ ObjectId ] id parent`s id
86+
# @param [ Document | Array ] element to push into the parent
87+
def set_on_parent(id, element)
88+
grouped_docs[id].each do |d|
89+
set_relation(d, element)
90+
end
91+
end
92+
93+
# Return a hash with the current documents grouped by key.
94+
#
95+
# Documents that do not have a value for the association being loaded
96+
# are not returned.
97+
#
98+
# @example Return a hash with the current documents grouped by key.
99+
# loader.grouped_docs
100+
#
101+
# @return [ Hash ] hash with grouped documents.
102+
def grouped_docs
103+
@grouped_docs[@association.name] ||= @docs.group_by do |doc|
104+
doc.send(group_by_key) if doc.respond_to?(group_by_key)
105+
end.reject do |k, v|
106+
k.nil?
107+
end
108+
end
109+
110+
# Group the documents and return the keys.
111+
#
112+
# This method omits nil keys (i.e. keys from documents that do not
113+
# have a value for the association being loaded).
114+
#
115+
# @example
116+
# loader.keys_from_docs
117+
#
118+
# @return [ Array ] keys, ids
119+
def keys_from_docs
120+
grouped_docs.keys
121+
end
122+
123+
# Return the key to group the current documents.
124+
#
125+
# This method should be implemented in the subclass
126+
#
127+
# @example Return the key for group
128+
# loader.group_by_key
129+
#
130+
# @return [ Symbol ] Key to group by the current documents.
131+
def group_by_key
132+
raise NotImplementedError
133+
end
134+
135+
# Set the pre-loaded document into its parent.
136+
#
137+
# @example Set docs into parent using the current association name.
138+
# loader.set_relation(doc, docs)
139+
#
140+
# @param [ Document ] doc The object to set the association on
141+
# @param [ Document | Array ] element to set into the parent
142+
def set_relation(doc, element)
143+
doc.set_relation(@association.name, element) unless doc.blank?
144+
end
145+
146+
private
147+
148+
# Shift the current association metadata
149+
#
150+
# @example Shift the current association.
151+
# loader.shift_association
152+
#
153+
# @return [ Mongoid::Association::Relatable ] The association object.
154+
def shift_association
155+
@association = @associations.shift
156+
end
157+
end
158+
end
159+
end

lib/mongoid/association/eager_loadable.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
require "mongoid/association/referenced/eager"
3+
require "mongoid/association/eager"
44

55
module Mongoid
66
module Association

lib/mongoid/association/embedded.rb

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'mongoid/association/embedded/cyclic'
4+
require 'mongoid/association/embedded/eager'
45
require 'mongoid/association/embedded/embedded_in'
56
require 'mongoid/association/embedded/embeds_many'
67
require 'mongoid/association/embedded/embeds_one'
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
module Mongoid
4+
module Association
5+
module Embedded
6+
7+
# Eager class for embedded associations (embedded_in, embeds_many,
8+
# embeds_one).
9+
class Eager < Association::Eager
10+
11+
private
12+
13+
# Embedded associations have no preload phase, since the embedded
14+
# documents are loaded with the parent document. This method is
15+
# implemented as a no-op to represent that.
16+
def preload
17+
end
18+
end
19+
20+
end
21+
end
22+
end

lib/mongoid/association/embedded/embedded_in/proxy.rb

+12
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ def persistable?
8181
end
8282

8383
class << self
84+
# Returns the eager loader for this association.
85+
#
86+
# @param [ Array<Mongoid::Association> ] associations The
87+
# associations to be eager loaded
88+
# @param [ Array<Mongoid::Document> ] docs The parent documents
89+
# that possess the given associations, which ought to be
90+
# populated by the eager-loaded documents.
91+
#
92+
# @return [ Mongoid::Association::Embedded::Eager ]
93+
def eager_loader(associations, docs)
94+
Eager.new(associations, docs)
95+
end
8496

8597
# Returns true if the association is an embedded one. In this case
8698
# always true.

lib/mongoid/association/embedded/embeds_many/proxy.rb

+12
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,18 @@ def update_attributes_hash
543543
end
544544

545545
class << self
546+
# Returns the eager loader for this association.
547+
#
548+
# @param [ Array<Mongoid::Association> ] associations The
549+
# associations to be eager loaded
550+
# @param [ Array<Mongoid::Document> ] docs The parent documents
551+
# that possess the given associations, which ought to be
552+
# populated by the eager-loaded documents.
553+
#
554+
# @return [ Mongoid::Association::Embedded::Eager ]
555+
def eager_loader(associations, docs)
556+
Eager.new(associations, docs)
557+
end
546558

547559
# Returns true if the association is an embedded one. In this case
548560
# always true.

lib/mongoid/association/embedded/embeds_one/proxy.rb

+12
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ def update_attributes_hash(replacement)
141141
end
142142

143143
class << self
144+
# Returns the eager loader for this association.
145+
#
146+
# @param [ Array<Mongoid::Association> ] associations The
147+
# associations to be eager loaded
148+
# @param [ Array<Mongoid::Document> ] docs The parent documents
149+
# that possess the given associations, which ought to be
150+
# populated by the eager-loaded documents.
151+
#
152+
# @return [ Mongoid::Association::Embedded::Eager ]
153+
def eager_loader(associations, docs)
154+
Eager.new(associations, docs)
155+
end
144156

145157
# Returns true if the association is an embedded one. In this case
146158
# always true.

lib/mongoid/association/referenced/belongs_to/eager.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Referenced
66
class BelongsTo
77

88
# Eager class for belongs_to associations.
9-
class Eager < Association::Referenced::Eager::Base
9+
class Eager < Association::Eager
1010

1111
private
1212

0 commit comments

Comments
 (0)