mongoid 7.0.0.beta → 7.0.0
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/config/locales/en.yml +21 -0
- data/lib/mongoid.rb +1 -1
- data/lib/mongoid/association/embedded/batchable.rb +39 -13
- data/lib/mongoid/association/many.rb +4 -0
- data/lib/mongoid/association/referenced/has_many.rb +2 -0
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +38 -7
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -2
- data/lib/mongoid/association/referenced/syncable.rb +1 -1
- data/lib/mongoid/association/touchable.rb +1 -1
- data/lib/mongoid/atomic.rb +3 -3
- data/lib/mongoid/atomic/modifiers.rb +12 -8
- data/lib/mongoid/attributes.rb +20 -12
- data/lib/mongoid/attributes/dynamic.rb +2 -2
- data/lib/mongoid/changeable.rb +1 -1
- data/lib/mongoid/clients.rb +2 -0
- data/lib/mongoid/clients/sessions.rb +113 -0
- data/lib/mongoid/clients/storage_options.rb +1 -0
- data/lib/mongoid/composable.rb +1 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +6 -3
- data/lib/mongoid/contextual/geo_near.rb +1 -1
- data/lib/mongoid/contextual/map_reduce.rb +6 -2
- data/lib/mongoid/contextual/memory.rb +25 -2
- data/lib/mongoid/contextual/mongo.rb +33 -14
- data/lib/mongoid/copyable.rb +2 -2
- data/lib/mongoid/criteria.rb +1 -0
- data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +3 -1
- data/lib/mongoid/errors.rb +1 -0
- data/lib/mongoid/errors/invalid_session_use.rb +24 -0
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/extensions/hash.rb +5 -2
- data/lib/mongoid/factory.rb +14 -5
- data/lib/mongoid/fields.rb +2 -2
- data/lib/mongoid/indexable.rb +4 -4
- data/lib/mongoid/matchable/and.rb +1 -1
- data/lib/mongoid/matchable/elem_match.rb +9 -3
- data/lib/mongoid/persistable.rb +2 -2
- data/lib/mongoid/persistable/creatable.rb +4 -2
- data/lib/mongoid/persistable/deletable.rb +4 -2
- data/lib/mongoid/persistable/destroyable.rb +1 -5
- data/lib/mongoid/persistable/updatable.rb +2 -2
- data/lib/mongoid/persistable/upsertable.rb +2 -1
- data/lib/mongoid/persistence_context.rb +5 -4
- data/lib/mongoid/query_cache.rb +5 -3
- data/lib/mongoid/reloadable.rb +1 -1
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/shardable.rb +1 -1
- data/lib/mongoid/tasks/database.rb +3 -2
- data/lib/mongoid/threaded.rb +38 -0
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -0
- data/spec/app/models/band.rb +1 -0
- data/spec/app/models/shipment_address.rb +1 -0
- data/spec/mongoid/association/macros_spec.rb +20 -0
- data/spec/mongoid/association/referenced/has_many/eager_spec.rb +15 -0
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +229 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
- data/spec/mongoid/atomic_spec.rb +17 -17
- data/spec/mongoid/attributes_spec.rb +38 -2
- data/spec/mongoid/clients/sessions_spec.rb +325 -0
- data/spec/mongoid/contextual/memory_spec.rb +19 -0
- data/spec/mongoid/contextual/mongo_spec.rb +133 -0
- data/spec/mongoid/copyable_spec.rb +34 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +43 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +32 -3
- data/spec/mongoid/extensions/hash_spec.rb +18 -1
- data/spec/mongoid/factory_spec.rb +11 -0
- data/spec/mongoid/interceptable_spec.rb +3 -1
- data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
- data/spec/mongoid/persistable/deletable_spec.rb +19 -0
- data/spec/mongoid/persistable/destroyable_spec.rb +19 -0
- data/spec/mongoid/persistable/savable_spec.rb +2 -2
- data/spec/mongoid/persistable/updatable_spec.rb +2 -2
- data/spec/mongoid/persistable_spec.rb +31 -16
- data/spec/mongoid/persistence_context_spec.rb +14 -0
- data/spec/mongoid/positional_spec.rb +10 -10
- data/spec/mongoid/query_cache_spec.rb +2 -16
- data/spec/mongoid/shardable_spec.rb +32 -12
- data/spec/spec_helper.rb +74 -0
- metadata +456 -446
- metadata.gz.sig +0 -0
@@ -259,7 +259,9 @@ module Mongoid
|
|
259
259
|
def prepare(field, operator, value)
|
260
260
|
unless operator =~ /exists|type|size/
|
261
261
|
value = value.__expand_complex__
|
262
|
-
|
262
|
+
field = field.to_s
|
263
|
+
name = aliases[field] || field
|
264
|
+
serializer = serializers[name]
|
263
265
|
value = serializer ? serializer.evolve(value) : value
|
264
266
|
end
|
265
267
|
selection = { operator => value }
|
data/lib/mongoid/errors.rb
CHANGED
@@ -20,6 +20,7 @@ require "mongoid/errors/invalid_persistence_option"
|
|
20
20
|
require "mongoid/errors/invalid_relation"
|
21
21
|
require "mongoid/errors/invalid_relation_option"
|
22
22
|
require "mongoid/errors/invalid_scope"
|
23
|
+
require "mongoid/errors/invalid_session_use"
|
23
24
|
require "mongoid/errors/invalid_set_polymorphic_relation"
|
24
25
|
require "mongoid/errors/invalid_storage_options"
|
25
26
|
require "mongoid/errors/invalid_storage_parent"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
# This error is raised when a session is attempted to be used with a model whose client cannot use it, if
|
6
|
+
# sessions are nested, or if the mongodb deployment doesn't support sessions.
|
7
|
+
#
|
8
|
+
# @since 6.4.0
|
9
|
+
class InvalidSessionUse < MongoidError
|
10
|
+
|
11
|
+
# Create the error.
|
12
|
+
#
|
13
|
+
# @example Create the error.
|
14
|
+
# InvalidSessionUse.new(:invalid_session_use)
|
15
|
+
#
|
16
|
+
# @param [ :invalid_sesion_use, :invalid_session_nesting ] error_type The type of session misuse.
|
17
|
+
#
|
18
|
+
# @since 6.4.0
|
19
|
+
def initialize(error_type)
|
20
|
+
super(compose_message(error_type.to_s))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/mongoid/extensions.rb
CHANGED
@@ -5,10 +5,6 @@ class BSON::ObjectId
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
-
class Symbol
|
9
|
-
remove_method :size if instance_methods.include? :size # temporal fix for ruby 1.9
|
10
|
-
end
|
11
|
-
|
12
8
|
class BSON::Document
|
13
9
|
# We need to override this as ActiveSupport creates a new Object, instead of a new Hash
|
14
10
|
# see https://github.com/rails/rails/commit/f1bad130d0c9bd77c94e43b696adca56c46a66aa
|
@@ -106,8 +106,11 @@ module Mongoid
|
|
106
106
|
value = self
|
107
107
|
keys.each do |key|
|
108
108
|
return nil if value.nil?
|
109
|
-
|
110
|
-
|
109
|
+
value_for_key = value[key]
|
110
|
+
if value_for_key.nil? && key.to_i.to_s == key
|
111
|
+
value_for_key = value[key.to_i]
|
112
|
+
end
|
113
|
+
value = value_for_key
|
111
114
|
end
|
112
115
|
value
|
113
116
|
end
|
data/lib/mongoid/factory.rb
CHANGED
@@ -17,7 +17,8 @@ module Mongoid
|
|
17
17
|
#
|
18
18
|
# @return [ Document ] The instantiated document.
|
19
19
|
def build(klass, attributes = nil)
|
20
|
-
|
20
|
+
attributes ||= {}
|
21
|
+
type = attributes[TYPE] || attributes[TYPE.to_sym]
|
21
22
|
if type && klass._types.include?(type)
|
22
23
|
type.constantize.new(attributes)
|
23
24
|
else
|
@@ -37,14 +38,22 @@ module Mongoid
|
|
37
38
|
# #only we give the document a list of the selected fields.
|
38
39
|
#
|
39
40
|
# @return [ Document ] The instantiated document.
|
40
|
-
def from_db(klass, attributes = nil,
|
41
|
+
def from_db(klass, attributes = nil, criteria = nil)
|
42
|
+
selected_fields = criteria.options[:fields] if criteria
|
41
43
|
type = (attributes || {})[TYPE]
|
42
44
|
if type.blank?
|
43
|
-
klass.instantiate(attributes, selected_fields)
|
45
|
+
obj = klass.instantiate(attributes, selected_fields)
|
46
|
+
if criteria && criteria.association && criteria.parent_document
|
47
|
+
obj.set_relation(criteria.association.inverse, criteria.parent_document)
|
48
|
+
end
|
49
|
+
obj
|
44
50
|
else
|
45
51
|
camelized = type.camelize
|
46
|
-
|
47
|
-
|
52
|
+
begin
|
53
|
+
camelized.constantize.instantiate(attributes, selected_fields)
|
54
|
+
rescue NameError
|
55
|
+
raise Errors::UnknownModel.new(camelized, type)
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
end
|
data/lib/mongoid/fields.rb
CHANGED
@@ -411,7 +411,7 @@ module Mongoid
|
|
411
411
|
def create_field_getter(name, meth, field)
|
412
412
|
generated_methods.module_eval do
|
413
413
|
re_define_method(meth) do
|
414
|
-
raw =
|
414
|
+
raw = read_raw_attribute(name)
|
415
415
|
if lazy_settable?(field, raw)
|
416
416
|
write_attribute(name, field.eval_default(self))
|
417
417
|
else
|
@@ -480,7 +480,7 @@ module Mongoid
|
|
480
480
|
def create_field_check(name, meth)
|
481
481
|
generated_methods.module_eval do
|
482
482
|
re_define_method("#{meth}?") do
|
483
|
-
value =
|
483
|
+
value = read_raw_attribute(name)
|
484
484
|
lookup_attribute_presence(name, value)
|
485
485
|
end
|
486
486
|
end
|
data/lib/mongoid/indexable.rb
CHANGED
@@ -35,10 +35,10 @@ module Mongoid
|
|
35
35
|
key, options = spec.key, default_options.merge(spec.options)
|
36
36
|
if database = options[:database]
|
37
37
|
with(database: database) do |klass|
|
38
|
-
klass.collection.indexes.create_one(key, options.except(:database))
|
38
|
+
klass.collection.indexes(session: session).create_one(key, options.except(:database))
|
39
39
|
end
|
40
40
|
else
|
41
|
-
collection.indexes.create_one(key, options)
|
41
|
+
collection.indexes(session: session).create_one(key, options)
|
42
42
|
end
|
43
43
|
end and true
|
44
44
|
end
|
@@ -56,9 +56,9 @@ module Mongoid
|
|
56
56
|
indexed_database_names.each do |database|
|
57
57
|
with(database: database) do |klass|
|
58
58
|
begin
|
59
|
-
klass.collection.indexes.each do |spec|
|
59
|
+
klass.collection.indexes(session: session).each do |spec|
|
60
60
|
unless spec["name"] == "_id_"
|
61
|
-
klass.collection.indexes.drop_one(spec["key"])
|
61
|
+
klass.collection.indexes(session: session).drop_one(spec["key"])
|
62
62
|
logger.info(
|
63
63
|
"MONGOID: Removed index '#{spec["name"]}' on collection " +
|
64
64
|
"'#{klass.collection.name}' in database '#{database}'."
|
@@ -13,13 +13,19 @@ module Mongoid
|
|
13
13
|
#
|
14
14
|
# @return [ true, false ] If the values match.
|
15
15
|
def _matches?(value)
|
16
|
-
|
16
|
+
elem_match = value["$elemMatch"] || value[:$elemMatch]
|
17
|
+
|
18
|
+
if !@attribute.is_a?(Array) || !value.kind_of?(Hash) || !elem_match.kind_of?(Hash)
|
17
19
|
return false
|
18
20
|
end
|
19
21
|
|
20
22
|
return @attribute.any? do |sub_document|
|
21
|
-
|
22
|
-
|
23
|
+
elem_match.all? do |k, v|
|
24
|
+
if v.try(:first).try(:[],0) == "$not".freeze || v.try(:first).try(:[],0) == :$not
|
25
|
+
!Matchable.matcher(sub_document, k, v.first[1])._matches?(v.first[1])
|
26
|
+
else
|
27
|
+
Matchable.matcher(sub_document, k, v)._matches?(v)
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
data/lib/mongoid/persistable.rb
CHANGED
@@ -201,9 +201,9 @@ module Mongoid
|
|
201
201
|
#
|
202
202
|
# @since 4.0.0
|
203
203
|
def persist_atomic_operations(operations)
|
204
|
-
if persisted? && operations
|
204
|
+
if persisted? && operations && !operations.empty?
|
205
205
|
selector = atomic_selector
|
206
|
-
_root.collection.find(selector).update_one(positionally(selector, operations))
|
206
|
+
_root.collection.find(selector).update_one(positionally(selector, operations), session: session)
|
207
207
|
end
|
208
208
|
end
|
209
209
|
end
|
@@ -61,7 +61,9 @@ module Mongoid
|
|
61
61
|
_parent.insert
|
62
62
|
else
|
63
63
|
selector = _parent.atomic_selector
|
64
|
-
_root.collection.find(selector).update_one(
|
64
|
+
_root.collection.find(selector).update_one(
|
65
|
+
positionally(selector, atomic_inserts),
|
66
|
+
session: session)
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -76,7 +78,7 @@ module Mongoid
|
|
76
78
|
#
|
77
79
|
# @since 4.0.0
|
78
80
|
def insert_as_root
|
79
|
-
collection.insert_one(as_attributes)
|
81
|
+
collection.insert_one(as_attributes, session: session)
|
80
82
|
end
|
81
83
|
|
82
84
|
# Post process an insert, which sets the new record attribute to false
|
@@ -64,7 +64,9 @@ module Mongoid
|
|
64
64
|
_parent.remove_child(self) if notifying_parent?(options)
|
65
65
|
if _parent.persisted?
|
66
66
|
selector = _parent.atomic_selector
|
67
|
-
_root.collection.find(selector).update_one(
|
67
|
+
_root.collection.find(selector).update_one(
|
68
|
+
positionally(selector, atomic_deletes),
|
69
|
+
session: session)
|
68
70
|
end
|
69
71
|
true
|
70
72
|
end
|
@@ -80,7 +82,7 @@ module Mongoid
|
|
80
82
|
#
|
81
83
|
# @since 4.0.0
|
82
84
|
def delete_as_root
|
83
|
-
collection.find(atomic_selector).delete_one
|
85
|
+
collection.find(atomic_selector).delete_one(session: session)
|
84
86
|
true
|
85
87
|
end
|
86
88
|
|
@@ -48,11 +48,7 @@ module Mongoid
|
|
48
48
|
#
|
49
49
|
# @since 1.0.0
|
50
50
|
def destroy_all(conditions = nil)
|
51
|
-
|
52
|
-
documents = where(selector)
|
53
|
-
destroyed = documents.count
|
54
|
-
documents.each { |doc| doc.destroy }
|
55
|
-
destroyed
|
51
|
+
where(conditions || {}).destroy
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
@@ -134,9 +134,9 @@ module Mongoid
|
|
134
134
|
unless updates.empty?
|
135
135
|
coll = collection(_root)
|
136
136
|
selector = atomic_selector
|
137
|
-
coll.find(selector).update_one(positionally(selector, updates))
|
137
|
+
coll.find(selector).update_one(positionally(selector, updates), session: session)
|
138
138
|
conflicts.each_pair do |key, value|
|
139
|
-
coll.find(selector).update_one(positionally(selector, { key => value }))
|
139
|
+
coll.find(selector).update_one(positionally(selector, { key => value }), session: session)
|
140
140
|
end
|
141
141
|
end
|
142
142
|
end
|
@@ -21,7 +21,8 @@ module Mongoid
|
|
21
21
|
# @since 3.0.0
|
22
22
|
def upsert(options = {})
|
23
23
|
prepare_upsert(options) do
|
24
|
-
collection.find(atomic_selector).update_one(
|
24
|
+
collection.find(atomic_selector).update_one(
|
25
|
+
as_attributes, upsert: true, session: session)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -195,10 +195,10 @@ module Mongoid
|
|
195
195
|
Thread.current["[mongoid][#{object.object_id}]:context"]
|
196
196
|
end
|
197
197
|
|
198
|
-
#
|
198
|
+
# Clear the persistence context for a particular class or model instance.
|
199
199
|
#
|
200
|
-
# @example
|
201
|
-
# PersistenceContext.
|
200
|
+
# @example Clear the persistence context for a class or model instance.
|
201
|
+
# PersistenceContext.clear(model)
|
202
202
|
#
|
203
203
|
# @param [ Class, Object ] object The class or model instance.
|
204
204
|
# @param [ Mongo::Cluster ] cluster The original cluster before this context was used.
|
@@ -208,8 +208,9 @@ module Mongoid
|
|
208
208
|
if context = get(object)
|
209
209
|
context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
|
210
210
|
end
|
211
|
+
ensure
|
211
212
|
Thread.current["[mongoid][#{object.object_id}]:context"] = nil
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
215
|
-
end
|
216
|
+
end
|
data/lib/mongoid/query_cache.rb
CHANGED
@@ -222,9 +222,11 @@ module Mongoid
|
|
222
222
|
super
|
223
223
|
else
|
224
224
|
unless cursor = cached_cursor
|
225
|
-
|
226
|
-
|
227
|
-
|
225
|
+
read_with_retry do
|
226
|
+
server = server_selector.select_server(cluster)
|
227
|
+
cursor = CachedCursor.new(view, send_initial_query(server), server)
|
228
|
+
QueryCache.cache_table[cache_key] = cursor
|
229
|
+
end
|
228
230
|
end
|
229
231
|
cursor.each do |doc|
|
230
232
|
yield doc
|
data/lib/mongoid/reloadable.rb
CHANGED
@@ -58,7 +58,7 @@ module Mongoid
|
|
58
58
|
#
|
59
59
|
# @since 2.3.2
|
60
60
|
def reload_root_document
|
61
|
-
{}.merge(collection.find(_id: _id).read(mode: :primary).first || {})
|
61
|
+
{}.merge(collection.find({ _id: _id }, session: session).read(mode: :primary).first || {})
|
62
62
|
end
|
63
63
|
|
64
64
|
# Reload the embedded document.
|
data/lib/mongoid/serializable.rb
CHANGED
@@ -101,7 +101,7 @@ module Mongoid
|
|
101
101
|
value = send(name)
|
102
102
|
attrs[name] = value ? value.serializable_hash(options) : nil
|
103
103
|
elsif names.include?(name) && !fields.key?(name)
|
104
|
-
attrs[name] =
|
104
|
+
attrs[name] = read_raw_attribute(name)
|
105
105
|
elsif !attribute_missing?(name)
|
106
106
|
attrs[name] = send(name)
|
107
107
|
end
|
data/lib/mongoid/shardable.rb
CHANGED
@@ -44,7 +44,7 @@ module Mongoid
|
|
44
44
|
models.each do |model|
|
45
45
|
unless model.embedded?
|
46
46
|
begin
|
47
|
-
model.collection.indexes.each do |index|
|
47
|
+
model.collection.indexes(session: model.send(:session)).each do |index|
|
48
48
|
# ignore default index
|
49
49
|
unless index['name'] == '_id_'
|
50
50
|
key = index['key'].symbolize_keys
|
@@ -77,7 +77,7 @@ module Mongoid
|
|
77
77
|
indexes.each do |index|
|
78
78
|
key = index['key'].symbolize_keys
|
79
79
|
collection = model.collection
|
80
|
-
collection.indexes.drop_one(key)
|
80
|
+
collection.indexes(session: model.send(:session)).drop_one(key)
|
81
81
|
logger.info(
|
82
82
|
"MONGOID: Removed index '#{index['name']}' on collection " +
|
83
83
|
"'#{collection.name}' in database '#{collection.database.name}'."
|
@@ -107,6 +107,7 @@ module Mongoid
|
|
107
107
|
end
|
108
108
|
|
109
109
|
private
|
110
|
+
|
110
111
|
def logger
|
111
112
|
Mongoid.logger
|
112
113
|
end
|
data/lib/mongoid/threaded.rb
CHANGED
@@ -325,5 +325,43 @@ module Mongoid
|
|
325
325
|
def validations_for(klass)
|
326
326
|
validations[klass] ||= []
|
327
327
|
end
|
328
|
+
|
329
|
+
# Cache a session for this thread.
|
330
|
+
#
|
331
|
+
# @example Save a session for this thread.
|
332
|
+
# Threaded.set_session(session)
|
333
|
+
#
|
334
|
+
# @param [ Mongo::Session ] session The session to save.
|
335
|
+
#
|
336
|
+
# @since 6.4.0
|
337
|
+
def set_session(session)
|
338
|
+
Thread.current[:session] = session
|
339
|
+
end
|
340
|
+
|
341
|
+
# Get the cached session for this thread.
|
342
|
+
#
|
343
|
+
# @example Get the session for this thread.
|
344
|
+
# Threaded.get_session
|
345
|
+
#
|
346
|
+
# @return [ Mongo::Session, nil ] The session cached on this thread or nil.
|
347
|
+
#
|
348
|
+
# @since 6.4.0
|
349
|
+
def get_session
|
350
|
+
Thread.current[:session]
|
351
|
+
end
|
352
|
+
|
353
|
+
# Clear the cached session for this thread.
|
354
|
+
#
|
355
|
+
# @example Clear this thread's session.
|
356
|
+
# Threaded.clear_session
|
357
|
+
#
|
358
|
+
# @return [ nil ]
|
359
|
+
#
|
360
|
+
# @since 6.4.0
|
361
|
+
def clear_session
|
362
|
+
session = get_session
|
363
|
+
session.end_session if session
|
364
|
+
Thread.current[:session] = nil
|
365
|
+
end
|
328
366
|
end
|
329
367
|
end
|
data/lib/mongoid/traversable.rb
CHANGED
data/lib/mongoid/version.rb
CHANGED
@@ -11,6 +11,10 @@ development:
|
|
11
11
|
hosts:
|
12
12
|
- localhost:27017
|
13
13
|
options:
|
14
|
+
# Note that all options listed below are Ruby driver client options (the mongo gem).
|
15
|
+
# Please refer to the driver documentation of the version of the mongo gem you are using
|
16
|
+
# for the most up-to-date list of options.
|
17
|
+
#
|
14
18
|
# Change the default write concern. (default = { w: 1 })
|
15
19
|
# write:
|
16
20
|
# w: 1
|