mongoid 3.0.0.rc → 3.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.
- data/CHANGELOG.md +109 -4
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/lib/config/locales/en.yml +15 -1
- data/lib/mongoid.rb +17 -2
- data/lib/mongoid/atomic.rb +54 -7
- data/lib/mongoid/attributes.rb +1 -1
- data/lib/mongoid/attributes/processing.rb +1 -1
- data/lib/mongoid/callbacks.rb +6 -1
- data/lib/mongoid/components.rb +2 -1
- data/lib/mongoid/config.rb +42 -17
- data/lib/mongoid/config/environment.rb +3 -1
- data/lib/mongoid/contextual/aggregable/memory.rb +21 -10
- data/lib/mongoid/contextual/find_and_modify.rb +14 -12
- data/lib/mongoid/contextual/memory.rb +24 -1
- data/lib/mongoid/contextual/mongo.rb +148 -29
- data/lib/mongoid/copyable.rb +6 -24
- data/lib/mongoid/criteria.rb +116 -34
- data/lib/mongoid/document.rb +7 -7
- data/lib/mongoid/errors.rb +1 -0
- data/lib/mongoid/errors/no_metadata.rb +21 -0
- data/lib/mongoid/evolvable.rb +19 -0
- data/lib/mongoid/extensions.rb +1 -1
- data/lib/mongoid/extensions/array.rb +38 -1
- data/lib/mongoid/extensions/big_decimal.rb +1 -1
- data/lib/mongoid/extensions/date_time.rb +6 -1
- data/lib/mongoid/extensions/false_class.rb +12 -0
- data/lib/mongoid/extensions/float.rb +12 -0
- data/lib/mongoid/extensions/hash.rb +33 -1
- data/lib/mongoid/extensions/integer.rb +12 -0
- data/lib/mongoid/extensions/object.rb +51 -1
- data/lib/mongoid/extensions/object_id.rb +2 -1
- data/lib/mongoid/extensions/range.rb +24 -0
- data/lib/mongoid/extensions/string.rb +31 -5
- data/lib/mongoid/extensions/true_class.rb +12 -0
- data/lib/mongoid/fields.rb +20 -21
- data/lib/mongoid/fields/foreign_key.rb +23 -7
- data/lib/mongoid/fields/standard.rb +3 -3
- data/lib/mongoid/finders.rb +3 -7
- data/lib/mongoid/hierarchy.rb +19 -1
- data/lib/mongoid/identity_map.rb +20 -4
- data/lib/mongoid/indexes/validators/options.rb +1 -1
- data/lib/mongoid/multi_parameter_attributes.rb +1 -1
- data/lib/mongoid/paranoia.rb +3 -32
- data/lib/mongoid/persistence.rb +33 -15
- data/lib/mongoid/persistence/atomic/operation.rb +1 -1
- data/lib/mongoid/persistence/operations.rb +16 -0
- data/lib/mongoid/persistence/operations/remove.rb +1 -1
- data/lib/mongoid/persistence/operations/upsert.rb +28 -0
- data/lib/mongoid/persistence/upsertion.rb +30 -0
- data/lib/mongoid/relations.rb +16 -0
- data/lib/mongoid/relations/accessors.rb +1 -1
- data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
- data/lib/mongoid/relations/builder.rb +1 -1
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/many.rb +1 -1
- data/lib/mongoid/relations/cascading.rb +4 -3
- data/lib/mongoid/relations/constraint.rb +1 -1
- data/lib/mongoid/relations/conversions.rb +1 -1
- data/lib/mongoid/relations/embedded/batchable.rb +3 -2
- data/lib/mongoid/relations/embedded/many.rb +4 -4
- data/lib/mongoid/relations/embedded/one.rb +1 -1
- data/lib/mongoid/relations/metadata.rb +67 -23
- data/lib/mongoid/relations/nested_builder.rb +2 -2
- data/lib/mongoid/relations/proxy.rb +9 -7
- data/lib/mongoid/relations/referenced/many.rb +69 -25
- data/lib/mongoid/relations/referenced/many_to_many.rb +14 -13
- data/lib/mongoid/scoping.rb +0 -17
- data/lib/mongoid/serialization.rb +95 -26
- data/lib/mongoid/sessions.rb +30 -6
- data/lib/mongoid/sessions/factory.rb +2 -0
- data/lib/mongoid/threaded.rb +52 -0
- data/lib/mongoid/timestamps/created.rb +1 -1
- data/lib/mongoid/timestamps/updated.rb +2 -1
- data/lib/mongoid/validations/uniqueness.rb +3 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +8 -0
- data/lib/rails/mongoid.rb +8 -5
- metadata +30 -13
- data/lib/mongoid/collections/retry.rb +0 -58
- data/lib/mongoid/javascript.rb +0 -20
- data/lib/mongoid/javascript/functions.yml +0 -63
@@ -112,12 +112,12 @@ module Mongoid
|
|
112
112
|
@metadata ||= options[:metadata]
|
113
113
|
end
|
114
114
|
|
115
|
-
# Is the field a BSON::ObjectId?
|
115
|
+
# Is the field a Moped::BSON::ObjectId?
|
116
116
|
#
|
117
|
-
# @example Is the field a BSON::ObjectId?
|
117
|
+
# @example Is the field a Moped::BSON::ObjectId?
|
118
118
|
# field.object_id_field?
|
119
119
|
#
|
120
|
-
# @return [ true, false ] If the field is a BSON::ObjectId.
|
120
|
+
# @return [ true, false ] If the field is a Moped::BSON::ObjectId.
|
121
121
|
#
|
122
122
|
# @since 2.2.0
|
123
123
|
def object_id_field?
|
data/lib/mongoid/finders.rb
CHANGED
@@ -52,7 +52,7 @@ module Mongoid
|
|
52
52
|
# on the conditions provided and the first parameter.
|
53
53
|
#
|
54
54
|
# @example Find a single document by an id.
|
55
|
-
# Person.find(BSON::ObjectId)
|
55
|
+
# Person.find(Moped::BSON::ObjectId)
|
56
56
|
#
|
57
57
|
# @param [ Array ] args An assortment of finder options.
|
58
58
|
#
|
@@ -112,9 +112,7 @@ module Mongoid
|
|
112
112
|
# Find the first +Document+ given the conditions.
|
113
113
|
#
|
114
114
|
# @example Find the first document.
|
115
|
-
# Person.first
|
116
|
-
#
|
117
|
-
# @param [ Array ] args The conditions with options.
|
115
|
+
# Person.first
|
118
116
|
#
|
119
117
|
# @return [ Document ] The first matching document.
|
120
118
|
def first
|
@@ -124,9 +122,7 @@ module Mongoid
|
|
124
122
|
# Find the last +Document+ given the conditions.
|
125
123
|
#
|
126
124
|
# @example Find the last document.
|
127
|
-
# Person.last
|
128
|
-
#
|
129
|
-
# @param [ Array ] args The conditions with options.
|
125
|
+
# Person.last
|
130
126
|
#
|
131
127
|
# @return [ Document ] The last matching document.
|
132
128
|
def last
|
data/lib/mongoid/hierarchy.rb
CHANGED
@@ -79,7 +79,7 @@ module Mongoid
|
|
79
79
|
#
|
80
80
|
# @since 2.0.0.beta.1
|
81
81
|
def remove_child(child)
|
82
|
-
name = child.
|
82
|
+
name = child.metadata_name
|
83
83
|
if child.embedded_one?
|
84
84
|
remove_ivar(name)
|
85
85
|
else
|
@@ -128,6 +128,24 @@ module Mongoid
|
|
128
128
|
def hereditary?
|
129
129
|
Mongoid::Document > superclass
|
130
130
|
end
|
131
|
+
|
132
|
+
# When inheriting, we want to copy the fields from the parent class and
|
133
|
+
# set the on the child to start, mimicking the behaviour of the old
|
134
|
+
# class_inheritable_accessor that was deprecated in Rails edge.
|
135
|
+
#
|
136
|
+
# @example Inherit from this class.
|
137
|
+
# Person.inherited(Doctor)
|
138
|
+
#
|
139
|
+
# @param [ Class ] subclass The inheriting class.
|
140
|
+
#
|
141
|
+
# @since 2.0.0.rc.6
|
142
|
+
def inherited(subclass)
|
143
|
+
super
|
144
|
+
subclass.fields = fields.dup
|
145
|
+
subclass.pre_processed_defaults = pre_processed_defaults.dup
|
146
|
+
subclass.post_processed_defaults = post_processed_defaults.dup
|
147
|
+
subclass.scopes = scopes.dup
|
148
|
+
end
|
131
149
|
end
|
132
150
|
end
|
133
151
|
end
|
data/lib/mongoid/identity_map.rb
CHANGED
@@ -16,8 +16,7 @@ module Mongoid
|
|
16
16
|
#
|
17
17
|
# @since 2.4.10
|
18
18
|
def clear_many(klass, selector)
|
19
|
-
|
20
|
-
documents.clear if documents
|
19
|
+
documents_for(klass)[selector] = {}
|
21
20
|
end
|
22
21
|
|
23
22
|
# Get a document from the identity map by its id.
|
@@ -44,6 +43,23 @@ module Mongoid
|
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
46
|
+
# Get many documents from the map via the selector
|
47
|
+
#
|
48
|
+
# @example Get the document from the map.
|
49
|
+
# map.get(Person, { post_id: post })
|
50
|
+
#
|
51
|
+
# @param [ Class ] klass The class of the document.
|
52
|
+
# @param [ Hash ] idenfier The selector.
|
53
|
+
#
|
54
|
+
# @return [ Array<Document> ] The matching documents.
|
55
|
+
#
|
56
|
+
# @since 3.0.0
|
57
|
+
def get_many(klass, identifier)
|
58
|
+
if Mongoid.using_identity_map? && klass
|
59
|
+
documents_for(klass)[identifier].try(:values)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
47
63
|
# Remove the document from the identity map.
|
48
64
|
#
|
49
65
|
# @example Remove the document.
|
@@ -88,7 +104,7 @@ module Mongoid
|
|
88
104
|
#
|
89
105
|
# @since 2.2.0
|
90
106
|
def set_many(document, selector)
|
91
|
-
(documents_for(document.class)[selector] ||= []
|
107
|
+
(documents_for(document.class)[selector] ||= {})[document.id] = document
|
92
108
|
end
|
93
109
|
|
94
110
|
# Set a document in the identity map for the provided selector.
|
@@ -103,7 +119,7 @@ module Mongoid
|
|
103
119
|
#
|
104
120
|
# @since 2.2.0
|
105
121
|
def set_one(document, selector)
|
106
|
-
|
122
|
+
documents_for(document.class)[selector] = document
|
107
123
|
end
|
108
124
|
|
109
125
|
private
|
@@ -7,7 +7,7 @@ module Mongoid
|
|
7
7
|
module Options
|
8
8
|
extend self
|
9
9
|
|
10
|
-
VALID_OPTIONS = [ :background, :drop_dups, :name, :sparse, :unique ]
|
10
|
+
VALID_OPTIONS = [ :background, :drop_dups, :name, :sparse, :unique, :max, :min ]
|
11
11
|
VALID_TYPES = [ 1, -1, "2d" ]
|
12
12
|
|
13
13
|
# Validate the index specification.
|
@@ -55,7 +55,7 @@ module Mongoid
|
|
55
55
|
multi_parameter_attributes = {}
|
56
56
|
|
57
57
|
attrs.each_pair do |key, value|
|
58
|
-
if key =~
|
58
|
+
if key =~ /\A([^\(]+)\((\d+)([if])\)$/
|
59
59
|
key, index = $1, $2.to_i
|
60
60
|
(multi_parameter_attributes[key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
|
61
61
|
else
|
data/lib/mongoid/paranoia.rb
CHANGED
@@ -16,6 +16,9 @@ module Mongoid
|
|
16
16
|
included do
|
17
17
|
field :deleted_at, type: Time
|
18
18
|
self.paranoid = true
|
19
|
+
|
20
|
+
default_scope where(deleted_at: nil)
|
21
|
+
scope :deleted, ne(deleted_at: nil)
|
19
22
|
end
|
20
23
|
|
21
24
|
# Delete the paranoid +Document+ from the database completely. This will
|
@@ -118,37 +121,5 @@ module Mongoid
|
|
118
121
|
def paranoid_field
|
119
122
|
embedded? ? "#{atomic_position}.deleted_at" : "deleted_at"
|
120
123
|
end
|
121
|
-
|
122
|
-
module ClassMethods
|
123
|
-
|
124
|
-
# Override the default +Criteria+ accessor to only get existing
|
125
|
-
# documents.
|
126
|
-
#
|
127
|
-
# @example Override the criteria.
|
128
|
-
# Person.queryable
|
129
|
-
#
|
130
|
-
# @param [ Array ] args The arguments.
|
131
|
-
#
|
132
|
-
# @return [ Criteria ] The paranoid compliant criteria.
|
133
|
-
#
|
134
|
-
# @since 3.0.0
|
135
|
-
def queryable
|
136
|
-
super.where(deleted_at: nil)
|
137
|
-
end
|
138
|
-
|
139
|
-
# Find deleted documents
|
140
|
-
#
|
141
|
-
# @example Find deleted documents.
|
142
|
-
# Person.deleted
|
143
|
-
# Company.first.employees.deleted
|
144
|
-
# Person.deleted.find("4c188dea7b17235a2a000001").first
|
145
|
-
#
|
146
|
-
# @return [ Criteria ] The deleted criteria.
|
147
|
-
#
|
148
|
-
# @since 1.0.0
|
149
|
-
def deleted
|
150
|
-
where(:deleted_at.ne => nil)
|
151
|
-
end
|
152
|
-
end
|
153
124
|
end
|
154
125
|
end
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -3,6 +3,7 @@ require "mongoid/persistence/atomic"
|
|
3
3
|
require "mongoid/persistence/deletion"
|
4
4
|
require "mongoid/persistence/insertion"
|
5
5
|
require "mongoid/persistence/modification"
|
6
|
+
require "mongoid/persistence/upsertion"
|
6
7
|
require "mongoid/persistence/operations"
|
7
8
|
|
8
9
|
module Mongoid
|
@@ -62,6 +63,25 @@ module Mongoid
|
|
62
63
|
end
|
63
64
|
alias :delete :remove
|
64
65
|
|
66
|
+
# Save the document - will perform an insert if the document is new, and
|
67
|
+
# update if not.
|
68
|
+
#
|
69
|
+
# @example Save the document.
|
70
|
+
# document.save
|
71
|
+
#
|
72
|
+
# @param [ Hash ] options Options to pass to the save.
|
73
|
+
#
|
74
|
+
# @return [ true, false ] True is success, false if not.
|
75
|
+
#
|
76
|
+
# @since 1.0.0
|
77
|
+
def save(options = {})
|
78
|
+
if new_record?
|
79
|
+
insert(options).persisted?
|
80
|
+
else
|
81
|
+
update(options)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
65
85
|
# Save the document - will perform an insert if the document is new, and
|
66
86
|
# update if not. If a validation error occurs an error will get raised.
|
67
87
|
#
|
@@ -72,8 +92,8 @@ module Mongoid
|
|
72
92
|
#
|
73
93
|
# @return [ true, false ] True if validation passed.
|
74
94
|
def save!(options = {})
|
75
|
-
unless
|
76
|
-
self.class.fail_validate!(self)
|
95
|
+
unless save(options)
|
96
|
+
self.class.fail_validate!(self) unless errors.empty?
|
77
97
|
self.class.fail_callback!(self, :save!)
|
78
98
|
end
|
79
99
|
return true
|
@@ -100,7 +120,7 @@ module Mongoid
|
|
100
120
|
current = Time.now
|
101
121
|
write_attribute(:updated_at, current) if fields["updated_at"]
|
102
122
|
write_attribute(field, current) if field
|
103
|
-
collection.find(atomic_selector).update(atomic_updates)
|
123
|
+
_root.collection.find(atomic_selector).update(atomic_updates)
|
104
124
|
without_autobuild do
|
105
125
|
touchables.each { |name| send(name).try(:touch) }
|
106
126
|
end
|
@@ -168,29 +188,27 @@ module Mongoid
|
|
168
188
|
def update_attributes!(attributes = {}, options = {})
|
169
189
|
result = update_attributes(attributes, options)
|
170
190
|
unless result
|
171
|
-
self.class.fail_validate!(self)
|
191
|
+
self.class.fail_validate!(self) unless errors.empty?
|
172
192
|
self.class.fail_callback!(self, :update_attributes!)
|
173
193
|
end
|
174
194
|
result
|
175
195
|
end
|
176
196
|
|
177
|
-
#
|
178
|
-
#
|
197
|
+
# Perform an upsert of the document. If the document does not exist in the
|
198
|
+
# database, then Mongo will insert a new one, otherwise the fields will get
|
199
|
+
# overwritten with new values on the existing document.
|
179
200
|
#
|
180
201
|
# @example Upsert the document.
|
181
202
|
# document.upsert
|
182
203
|
#
|
183
|
-
# @param [ Hash ] options
|
204
|
+
# @param [ Hash ] options The validation options.
|
184
205
|
#
|
185
|
-
# @return [ true
|
206
|
+
# @return [ true ] True.
|
207
|
+
#
|
208
|
+
# @since 3.0.0
|
186
209
|
def upsert(options = {})
|
187
|
-
|
188
|
-
insert(options).persisted?
|
189
|
-
else
|
190
|
-
update(options)
|
191
|
-
end
|
210
|
+
Operations.upsert(self, options).persist
|
192
211
|
end
|
193
|
-
alias :save :upsert
|
194
212
|
|
195
213
|
module ClassMethods #:nodoc:
|
196
214
|
|
@@ -230,7 +248,7 @@ module Mongoid
|
|
230
248
|
def create!(attributes = {}, options = {}, &block)
|
231
249
|
_creating do
|
232
250
|
doc = new(attributes, options, &block)
|
233
|
-
fail_validate!(doc)
|
251
|
+
fail_validate!(doc) unless doc.insert.errors.empty?
|
234
252
|
fail_callback!(doc, :create!) if doc.new_record?
|
235
253
|
doc
|
236
254
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
require "mongoid/persistence/operations/insert"
|
3
3
|
require "mongoid/persistence/operations/remove"
|
4
4
|
require "mongoid/persistence/operations/update"
|
5
|
+
require "mongoid/persistence/operations/upsert"
|
5
6
|
require "mongoid/persistence/operations/embedded/insert"
|
6
7
|
require "mongoid/persistence/operations/embedded/remove"
|
7
8
|
|
@@ -192,6 +193,21 @@ module Mongoid
|
|
192
193
|
def update(doc, options = {})
|
193
194
|
Update.new(doc, options)
|
194
195
|
end
|
196
|
+
|
197
|
+
# Get the appropriate upsert operation based on the document.
|
198
|
+
#
|
199
|
+
# @example Get the upsert operation.
|
200
|
+
# Operations.upsert(doc, options)
|
201
|
+
#
|
202
|
+
# @param [ Document ] doc The document to persist.
|
203
|
+
# @param [ Hash ] options The persistence options.
|
204
|
+
#
|
205
|
+
# @return [ Operations ] The operation.
|
206
|
+
#
|
207
|
+
# @since 3.0.0
|
208
|
+
def upsert(doc, options = {})
|
209
|
+
Upsert.new(doc, options)
|
210
|
+
end
|
195
211
|
end
|
196
212
|
end
|
197
213
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistence
|
4
|
+
module Operations
|
5
|
+
|
6
|
+
# Wraps behaviour for performing upserts in Mongodb. No matter if the
|
7
|
+
# document has been modified or not, it will be sent to the db and Mongo
|
8
|
+
# will determin whether or not to insert or update.
|
9
|
+
class Upsert
|
10
|
+
include Upsertion, Operations
|
11
|
+
|
12
|
+
# Persist the upsert operation.
|
13
|
+
#
|
14
|
+
# @example Execute the upsert.
|
15
|
+
# operation.persist
|
16
|
+
#
|
17
|
+
# @return [ true ] Always true.
|
18
|
+
#
|
19
|
+
# @since 3.0.0
|
20
|
+
def persist
|
21
|
+
prepare do
|
22
|
+
collection.find(selector).update(document.as_document, [ :upsert ])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistence
|
4
|
+
|
5
|
+
# Contains common logic for upsert operations.
|
6
|
+
module Upsertion
|
7
|
+
|
8
|
+
# Wrap all the common upsert logic for root docments.
|
9
|
+
#
|
10
|
+
# @example Execute common upsert logic.
|
11
|
+
# prepare do |doc|
|
12
|
+
# collection.find({ :_id => 1 }).upsert({ name: "test" }, [ :upsert ])
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# @param [ Proc ] block The block to call.
|
16
|
+
#
|
17
|
+
# @return [ true, false ] If the save passed or not.
|
18
|
+
#
|
19
|
+
# @since 3.0.0
|
20
|
+
def prepare(&block)
|
21
|
+
return false if validating? && document.invalid?(:upsert)
|
22
|
+
result = document.run_callbacks(:upsert) do
|
23
|
+
yield(document); true
|
24
|
+
end
|
25
|
+
document.post_persist unless result == false
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/mongoid/relations.rb
CHANGED
@@ -83,6 +83,22 @@ module Mongoid
|
|
83
83
|
metadata && metadata.macro == :embeds_one
|
84
84
|
end
|
85
85
|
|
86
|
+
# Get the metadata name for this document. If no metadata was defined
|
87
|
+
# will raise an error.
|
88
|
+
#
|
89
|
+
# @example Get the metadata name.
|
90
|
+
# document.metadata_name
|
91
|
+
#
|
92
|
+
# @raise [ Errors::NoMetadata ] If no metadata is present.
|
93
|
+
#
|
94
|
+
# @return [ Symbol ] The metadata name.
|
95
|
+
#
|
96
|
+
# @since 3.0.0
|
97
|
+
def metadata_name
|
98
|
+
raise Errors::NoMetadata.new(self.class.name) unless metadata
|
99
|
+
metadata.name
|
100
|
+
end
|
101
|
+
|
86
102
|
# Determine if the document is part of an references_many relation.
|
87
103
|
#
|
88
104
|
# @example Is the document in a references many?
|
@@ -15,7 +15,7 @@ module Mongoid
|
|
15
15
|
# person.__build__(:addresses, { :id => 1 }, metadata)
|
16
16
|
#
|
17
17
|
# @param [ String, Symbol ] name The name of the relation.
|
18
|
-
# @param [ Hash, BSON::ObjectId ] object The id or attributes to use.
|
18
|
+
# @param [ Hash, Moped::BSON::ObjectId ] object The id or attributes to use.
|
19
19
|
# @param [ Metadata ] metadata The relation's metadata.
|
20
20
|
# @param [ true, false ] building If we are in a build operation.
|
21
21
|
#
|
@@ -25,7 +25,7 @@ module Mongoid
|
|
25
25
|
bind_polymorphic_inverse_type(base, target.class.model_name)
|
26
26
|
if inverse = metadata.inverse(target)
|
27
27
|
if set_base_metadata
|
28
|
-
bind_inverse_of_field(base, base.
|
28
|
+
bind_inverse_of_field(base, base.metadata_name)
|
29
29
|
if base.referenced_many?
|
30
30
|
target.__send__(inverse).push(base) unless Mongoid.using_identity_map?
|
31
31
|
else
|