mongoid 7.2.0.rc1 → 7.3.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +45 -10
- data/lib/config/locales/en.yml +2 -2
- data/lib/mongoid/association/accessors.rb +1 -1
- data/lib/mongoid/association/constrainable.rb +1 -1
- data/lib/mongoid/association/depending.rb +4 -4
- data/lib/mongoid/association/embedded/batchable.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
- data/lib/mongoid/association/nested/many.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +4 -2
- data/lib/mongoid/association/proxy.rb +6 -1
- data/lib/mongoid/association/referenced/auto_save.rb +2 -2
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/buildable.rb +8 -0
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
- data/lib/mongoid/attributes.rb +32 -14
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/cacheable.rb +2 -2
- data/lib/mongoid/clients.rb +1 -1
- data/lib/mongoid/clients/factory.rb +22 -8
- data/lib/mongoid/config.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- data/lib/mongoid/copyable.rb +6 -2
- data/lib/mongoid/criteria.rb +4 -5
- data/lib/mongoid/criteria/findable.rb +1 -1
- data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
- data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
- data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
- data/lib/mongoid/criteria/queryable/selector.rb +0 -4
- data/lib/mongoid/document.rb +4 -17
- data/lib/mongoid/errors/delete_restriction.rb +8 -9
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/boolean.rb +1 -2
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +2 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/fields.rb +46 -5
- data/lib/mongoid/inspectable.rb +1 -1
- data/lib/mongoid/interceptable.rb +3 -1
- data/lib/mongoid/matcher.rb +26 -43
- data/lib/mongoid/matcher/bits.rb +41 -0
- data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_all_set.rb +20 -0
- data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_any_set.rb +20 -0
- data/lib/mongoid/matcher/elem_match.rb +2 -1
- data/lib/mongoid/matcher/expression.rb +9 -14
- data/lib/mongoid/matcher/field_expression.rb +4 -5
- data/lib/mongoid/matcher/field_operator.rb +13 -11
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/persistable/deletable.rb +1 -2
- data/lib/mongoid/persistable/destroyable.rb +8 -2
- data/lib/mongoid/persistable/updatable.rb +27 -2
- data/lib/mongoid/query_cache.rb +35 -29
- data/lib/mongoid/reloadable.rb +5 -0
- data/lib/mongoid/selectable.rb +5 -7
- data/lib/mongoid/shardable.rb +21 -5
- data/lib/mongoid/stringified_symbol.rb +53 -0
- data/lib/mongoid/touchable.rb +23 -4
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
- data/spec/README.md +19 -4
- data/spec/integration/app_spec.rb +175 -88
- data/spec/integration/associations/embeds_many_spec.rb +68 -0
- data/spec/integration/associations/embeds_one_spec.rb +24 -0
- data/spec/integration/associations/has_many_spec.rb +60 -0
- data/spec/integration/associations/has_one_spec.rb +108 -0
- data/spec/integration/callbacks_models.rb +49 -0
- data/spec/integration/callbacks_spec.rb +216 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/document_spec.rb +30 -0
- data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
- data/spec/integration/matcher_operator_data/comment.yml +22 -0
- data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
- data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
- data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
- data/spec/integration/matcher_operator_data/in.yml +16 -0
- data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
- data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
- data/spec/integration/matcher_operator_data/type.yml +70 -0
- data/spec/integration/matcher_operator_data/type_array.yml +16 -0
- data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
- data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
- data/spec/integration/matcher_operator_data/type_code.yml +26 -0
- data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
- data/spec/integration/matcher_operator_data/type_date.yml +39 -0
- data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
- data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
- data/spec/integration/matcher_operator_data/type_double.yml +15 -0
- data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
- data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
- data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_null.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
- data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
- data/spec/integration/matcher_operator_data/type_string.yml +15 -0
- data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
- data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
- data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
- data/spec/integration/stringified_symbol_field_spec.rb +190 -0
- data/spec/lite_spec_helper.rb +9 -7
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
- data/spec/mongoid/association/nested/one_spec.rb +18 -14
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many_models.rb +12 -0
- data/spec/mongoid/association/referenced/has_one_models.rb +20 -0
- data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
- data/spec/mongoid/atomic/paths_spec.rb +105 -12
- data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
- data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
- data/spec/mongoid/attributes/projector_spec.rb +41 -0
- data/spec/mongoid/attributes_spec.rb +333 -0
- data/spec/mongoid/clients/factory_spec.rb +48 -0
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/atomic_spec.rb +17 -4
- data/spec/mongoid/contextual/mongo_spec.rb +2 -2
- data/spec/mongoid/copyable_spec.rb +44 -17
- data/spec/mongoid/copyable_spec_models.rb +14 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
- data/spec/mongoid/criteria_projection_spec.rb +411 -0
- data/spec/mongoid/criteria_spec.rb +0 -275
- data/spec/mongoid/document_fields_spec.rb +26 -0
- data/spec/mongoid/document_spec.rb +13 -13
- data/spec/mongoid/equality_spec.rb +0 -1
- data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
- data/spec/mongoid/extensions/false_class_spec.rb +1 -1
- data/spec/mongoid/extensions/string_spec.rb +5 -5
- data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
- data/spec/mongoid/extensions/true_class_spec.rb +1 -1
- data/spec/mongoid/fields/localized_spec.rb +4 -4
- data/spec/mongoid/fields_spec.rb +4 -4
- data/spec/mongoid/inspectable_spec.rb +12 -4
- data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
- data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
- data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
- data/spec/mongoid/persistable/deletable_spec.rb +175 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
- data/spec/mongoid/persistable/savable_spec.rb +3 -5
- data/spec/mongoid/persistable/settable_spec.rb +30 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
- data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
- data/spec/mongoid/reloadable_spec.rb +18 -1
- data/spec/mongoid/shardable_spec.rb +44 -0
- data/spec/mongoid/touchable_spec.rb +104 -16
- data/spec/mongoid/touchable_spec_models.rb +52 -0
- data/spec/mongoid/validatable_spec.rb +1 -1
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +221 -0
- data/spec/shared/lib/mrss/constraints.rb +354 -0
- data/spec/shared/lib/mrss/docker_runner.rb +265 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +231 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +290 -0
- data/spec/shared/shlib/set_env.sh +128 -0
- data/spec/spec_helper.rb +7 -1
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/constraints.rb +0 -226
- data/spec/support/models/bolt.rb +8 -0
- data/spec/support/models/customer.rb +11 -0
- data/spec/support/models/customer_address.rb +12 -0
- data/spec/support/models/dictionary.rb +6 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/support/models/mop.rb +9 -0
- data/spec/support/models/nut.rb +8 -0
- data/spec/support/models/order.rb +11 -0
- data/spec/support/models/person.rb +8 -0
- data/spec/support/models/sealer.rb +8 -0
- data/spec/support/models/series.rb +1 -0
- data/spec/support/models/shirt.rb +12 -0
- data/spec/support/models/spacer.rb +8 -0
- data/spec/support/models/threadlocker.rb +8 -0
- data/spec/support/models/washer.rb +8 -0
- data/spec/support/models/wiki_page.rb +1 -0
- data/spec/support/spec_config.rb +8 -0
- metadata +655 -507
- metadata.gz.sig +0 -0
- data/spec/support/child_process_helper.rb +0 -79
- data/spec/support/cluster_config.rb +0 -158
- data/spec/support/lite_constraints.rb +0 -22
- data/spec/support/spec_organizer.rb +0 -130
|
@@ -47,7 +47,7 @@ module Mongoid
|
|
|
47
47
|
#
|
|
48
48
|
# @since 4.0.0
|
|
49
49
|
def atomic_deletes
|
|
50
|
-
{ atomic_delete_modifier => { atomic_path => _index ? { "_id" =>
|
|
50
|
+
{ atomic_delete_modifier => { atomic_path => _index ? { "_id" => _id } : true }}
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Delete the embedded document.
|
|
@@ -117,7 +117,6 @@ module Mongoid
|
|
|
117
117
|
#
|
|
118
118
|
# @since 4.0.0
|
|
119
119
|
def prepare_delete
|
|
120
|
-
return false unless catch(:abort) { apply_delete_dependencies! }
|
|
121
120
|
yield(self)
|
|
122
121
|
freeze
|
|
123
122
|
self.destroyed = true
|
|
@@ -23,13 +23,19 @@ module Mongoid
|
|
|
23
23
|
def destroy(options = nil)
|
|
24
24
|
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
|
25
25
|
self.flagged_for_destroy = true
|
|
26
|
-
result = run_callbacks(:destroy)
|
|
26
|
+
result = run_callbacks(:destroy) do
|
|
27
|
+
if catch(:abort) { apply_destroy_dependencies! }
|
|
28
|
+
delete(options || {})
|
|
29
|
+
else
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
27
33
|
self.flagged_for_destroy = false
|
|
28
34
|
result
|
|
29
35
|
end
|
|
30
36
|
|
|
31
37
|
def destroy!(options = {})
|
|
32
|
-
destroy || raise(Errors::DocumentNotDestroyed.new(
|
|
38
|
+
destroy || raise(Errors::DocumentNotDestroyed.new(_id, self.class))
|
|
33
39
|
end
|
|
34
40
|
|
|
35
41
|
module ClassMethods
|
|
@@ -137,8 +137,33 @@ module Mongoid
|
|
|
137
137
|
coll = collection(_root)
|
|
138
138
|
selector = atomic_selector
|
|
139
139
|
coll.find(selector).update_one(positionally(selector, updates), session: _session)
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
|
|
141
|
+
# The following code applies updates which would cause
|
|
142
|
+
# path conflicts in MongoDB, for example when changing attributes
|
|
143
|
+
# of foo.0.bars while adding another foo. Each conflicting update
|
|
144
|
+
# is applied using its own write.
|
|
145
|
+
#
|
|
146
|
+
# TODO: MONGOID-5026: reduce the number of writes performed by
|
|
147
|
+
# more intelligently combining the writes such that there are
|
|
148
|
+
# fewer conflicts.
|
|
149
|
+
conflicts.each_pair do |modifier, changes|
|
|
150
|
+
|
|
151
|
+
# Group the changes according to their root key which is
|
|
152
|
+
# the top-level association name.
|
|
153
|
+
# This handles at least the cases described in MONGOID-4982.
|
|
154
|
+
conflicting_change_groups = changes.group_by do |key, _|
|
|
155
|
+
key.split(".", 2).first
|
|
156
|
+
end.values
|
|
157
|
+
|
|
158
|
+
# Apply changes in batches. Pop one change from each
|
|
159
|
+
# field-conflict group round-robin until all changes
|
|
160
|
+
# have been applied.
|
|
161
|
+
while batched_changes = conflicting_change_groups.map(&:pop).compact.to_h.presence
|
|
162
|
+
coll.find(selector).update_one(
|
|
163
|
+
positionally(selector, modifier => batched_changes),
|
|
164
|
+
session: _session,
|
|
165
|
+
)
|
|
166
|
+
end
|
|
142
167
|
end
|
|
143
168
|
end
|
|
144
169
|
end
|
data/lib/mongoid/query_cache.rb
CHANGED
|
@@ -117,38 +117,44 @@ module Mongoid
|
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
# Instantiate the middleware.
|
|
127
|
-
#
|
|
128
|
-
# @example Create the new middleware.
|
|
129
|
-
# Middleware.new(app)
|
|
130
|
-
#
|
|
131
|
-
# @param [ Object ] app The rack applciation stack.
|
|
120
|
+
if defined?(Mongo::QueryCache::Middleware)
|
|
121
|
+
Middleware = Mongo::QueryCache::Middleware
|
|
122
|
+
else
|
|
123
|
+
# The middleware to be added to a rack application in order to activate the
|
|
124
|
+
# query cache.
|
|
132
125
|
#
|
|
133
126
|
# @since 4.0.0
|
|
134
|
-
|
|
135
|
-
@app = app
|
|
136
|
-
end
|
|
127
|
+
class Middleware
|
|
137
128
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
129
|
+
# Instantiate the middleware.
|
|
130
|
+
#
|
|
131
|
+
# @example Create the new middleware.
|
|
132
|
+
# Middleware.new(app)
|
|
133
|
+
#
|
|
134
|
+
# @param [ Object ] app The rack application stack.
|
|
135
|
+
#
|
|
136
|
+
# @since 4.0.0
|
|
137
|
+
def initialize(app)
|
|
138
|
+
@app = app
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Execute the request, wrapping in a query cache.
|
|
142
|
+
#
|
|
143
|
+
# @example Execute the request.
|
|
144
|
+
# middleware.call(env)
|
|
145
|
+
#
|
|
146
|
+
# @param [ Object ] env The environment.
|
|
147
|
+
#
|
|
148
|
+
# @return [ Object ] The result of the call.
|
|
149
|
+
#
|
|
150
|
+
# @since 4.0.0
|
|
151
|
+
def call(env)
|
|
152
|
+
QueryCache.cache do
|
|
153
|
+
@app.call(env)
|
|
154
|
+
end
|
|
155
|
+
ensure
|
|
156
|
+
QueryCache.clear_cache
|
|
157
|
+
end
|
|
152
158
|
end
|
|
153
159
|
end
|
|
154
160
|
|
data/lib/mongoid/reloadable.rb
CHANGED
|
@@ -21,6 +21,11 @@ module Mongoid
|
|
|
21
21
|
#
|
|
22
22
|
# @since 1.0.0
|
|
23
23
|
def reload
|
|
24
|
+
if @atomic_selector
|
|
25
|
+
# Clear atomic_selector cache for sharded clusters. MONGOID-5076
|
|
26
|
+
remove_instance_variable('@atomic_selector')
|
|
27
|
+
end
|
|
28
|
+
|
|
24
29
|
reloaded = _reload
|
|
25
30
|
if Mongoid.raise_not_found_error && reloaded.empty?
|
|
26
31
|
raise Errors::DocumentNotFound.new(self.class, _id, _id)
|
data/lib/mongoid/selectable.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Mongoid
|
|
|
21
21
|
# @since 1.0.0
|
|
22
22
|
def atomic_selector
|
|
23
23
|
@atomic_selector ||=
|
|
24
|
-
(embedded? ? embedded_atomic_selector :
|
|
24
|
+
(embedded? ? embedded_atomic_selector : root_atomic_selector_in_db)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
private
|
|
@@ -44,18 +44,16 @@ module Mongoid
|
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
# Get the atomic selector
|
|
47
|
+
# Get the atomic selector that would match the existing version of the
|
|
48
|
+
# root document.
|
|
48
49
|
#
|
|
49
50
|
# @api private
|
|
50
51
|
#
|
|
51
|
-
# @example Get the root atomic selector.
|
|
52
|
-
# document.root_atomic_selector
|
|
53
|
-
#
|
|
54
52
|
# @return [ Hash ] The root document selector.
|
|
55
53
|
#
|
|
56
54
|
# @since 4.0.0
|
|
57
|
-
def
|
|
58
|
-
{ "_id" => _id }.merge!(
|
|
55
|
+
def root_atomic_selector_in_db
|
|
56
|
+
{ "_id" => _id }.merge!(shard_key_selector_in_db)
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
end
|
data/lib/mongoid/shardable.rb
CHANGED
|
@@ -52,15 +52,31 @@ module Mongoid
|
|
|
52
52
|
self.class.shard_key_fields
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# @example Get the selector for the shard keys.
|
|
58
|
-
# person.shard_key_selector
|
|
55
|
+
# Returns the selector that would match the current version of this
|
|
56
|
+
# document.
|
|
59
57
|
#
|
|
60
58
|
# @return [ Hash ] The shard key selector.
|
|
61
59
|
#
|
|
62
|
-
# @
|
|
60
|
+
# @api private
|
|
63
61
|
def shard_key_selector
|
|
62
|
+
selector = {}
|
|
63
|
+
shard_key_fields.each do |field|
|
|
64
|
+
selector[field.to_s] = send(field)
|
|
65
|
+
end
|
|
66
|
+
selector
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns the selector that would match the existing version of this
|
|
70
|
+
# document in the database.
|
|
71
|
+
#
|
|
72
|
+
# If the document is not persisted, this method uses the current values
|
|
73
|
+
# of the shard key fields. If the document is persisted, this method
|
|
74
|
+
# uses the values retrieved from the database.
|
|
75
|
+
#
|
|
76
|
+
# @return [ Hash ] The shard key selector.
|
|
77
|
+
#
|
|
78
|
+
# @api private
|
|
79
|
+
def shard_key_selector_in_db
|
|
64
80
|
selector = {}
|
|
65
81
|
shard_key_fields.each do |field|
|
|
66
82
|
selector[field.to_s] = new_record? ? send(field) : attribute_was(field)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
# A class which sends values to the database as Strings but returns them to the user as Symbols.
|
|
5
|
+
module Mongoid
|
|
6
|
+
class StringifiedSymbol
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
|
|
10
|
+
# Convert the object from its mongo friendly ruby type to this type.
|
|
11
|
+
#
|
|
12
|
+
# @example Demongoize the object.
|
|
13
|
+
# Symbol.demongoize(object)
|
|
14
|
+
#
|
|
15
|
+
# @param [ Object ] object The object to demongoize.
|
|
16
|
+
#
|
|
17
|
+
# @return [ Symbol ] The object.
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
20
|
+
def demongoize(object)
|
|
21
|
+
if object.nil?
|
|
22
|
+
object
|
|
23
|
+
else
|
|
24
|
+
object.to_s.to_sym
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Turn the object from the ruby type we deal with to a Mongo friendly
|
|
29
|
+
# type.
|
|
30
|
+
#
|
|
31
|
+
# @example Mongoize the object.
|
|
32
|
+
# Symbol.mongoize("123.11")
|
|
33
|
+
#
|
|
34
|
+
# @param [ Object ] object The object to mongoize.
|
|
35
|
+
#
|
|
36
|
+
# @return [ Symbol ] The object mongoized.
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
def mongoize(object)
|
|
40
|
+
if object.nil?
|
|
41
|
+
object
|
|
42
|
+
else
|
|
43
|
+
object.to_s
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @api private
|
|
48
|
+
def evolve(object)
|
|
49
|
+
mongoize(object)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/mongoid/touchable.rb
CHANGED
|
@@ -30,11 +30,30 @@ module Mongoid
|
|
|
30
30
|
write_attribute(:updated_at, current) if respond_to?("updated_at=")
|
|
31
31
|
write_attribute(field, current) if field
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
# If the document being touched is embedded, touch its parents
|
|
34
|
+
# all the way through the composition hierarchy to the root object,
|
|
35
|
+
# because when an embedded document is changed the write is actually
|
|
36
|
+
# performed by the composition root. See MONGOID-3468.
|
|
37
|
+
if _parent
|
|
38
|
+
# This will persist updated_at on this document as well as parents.
|
|
39
|
+
# TODO support passing the field name to the parent's touch method;
|
|
40
|
+
# I believe it should be read out of
|
|
41
|
+
# _association.inverse_association.options but inverse_association
|
|
42
|
+
# seems to not always/ever be set here. See MONGOID-5014.
|
|
43
|
+
_parent.touch
|
|
44
|
+
else
|
|
45
|
+
# If the current document is not embedded, it is composition root
|
|
46
|
+
# and we need to persist the write here.
|
|
47
|
+
touches = touch_atomic_updates(field)
|
|
48
|
+
unless touches["$set"].blank?
|
|
49
|
+
selector = atomic_selector
|
|
50
|
+
_root.collection.find(selector).update_one(positionally(selector, touches), session: _session)
|
|
51
|
+
end
|
|
37
52
|
end
|
|
53
|
+
|
|
54
|
+
# Callbacks are invoked on the composition root first and on the
|
|
55
|
+
# leaf-most embedded document last.
|
|
56
|
+
# TODO add tests, see MONGOID-5015.
|
|
38
57
|
run_callbacks(:touch)
|
|
39
58
|
true
|
|
40
59
|
end
|
data/lib/mongoid/version.rb
CHANGED
|
@@ -15,7 +15,14 @@ module Mongoid
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def app_name
|
|
18
|
-
Rails
|
|
18
|
+
app_cls = Rails.application.class
|
|
19
|
+
parent = begin
|
|
20
|
+
# Rails 6.1+
|
|
21
|
+
app_cls.module_parent_name
|
|
22
|
+
rescue NoMethodError
|
|
23
|
+
app_cls.parent.to_s
|
|
24
|
+
end
|
|
25
|
+
parent.underscore
|
|
19
26
|
end
|
|
20
27
|
|
|
21
28
|
def create_config_file
|
data/spec/README.md
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
# Running Mongoid Tests
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
The test suite requires shared tooling that is stored in a separate repository
|
|
6
|
+
and is referenced as a submodule. After checking out the desired driver
|
|
7
|
+
branch, check out the matching submodules:
|
|
8
|
+
|
|
9
|
+
git submodule init
|
|
10
|
+
git submodule update
|
|
11
|
+
|
|
12
|
+
Spin up a MongoDB deployment against which to run the Mongoid specs.
|
|
13
|
+
Mongoid specs support a variety of MongoDB topologies, but the simplest is
|
|
14
|
+
a single MongoDB instance:
|
|
6
15
|
|
|
7
16
|
# Launch mongod in one terminal
|
|
8
17
|
mkdir /tmp/mdb
|
|
@@ -14,5 +23,11 @@ Run the test suite in a separate terminal:
|
|
|
14
23
|
|
|
15
24
|
|
|
16
25
|
## Caveats
|
|
26
|
+
|
|
17
27
|
### "Too many open files" error
|
|
18
|
-
|
|
28
|
+
|
|
29
|
+
On MacOS, you may encounter a "Too many open files" error on the MongoDB server
|
|
30
|
+
when running the tests. If this happens, stop the server, run the command
|
|
31
|
+
`ulimit -n 10000` in the same terminal session as the server, and restart
|
|
32
|
+
the server. This will increase the number of files that can be opened.
|
|
33
|
+
Then, re-run the tests.
|
|
@@ -13,109 +13,131 @@ describe 'Mongoid application tests' do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
require 'fileutils'
|
|
16
|
-
require '
|
|
16
|
+
require 'mrss/child_process_helper'
|
|
17
17
|
require 'open-uri'
|
|
18
18
|
|
|
19
19
|
FileUtils.mkdir_p(TMP_BASE)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
context 'demo application
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
context 'demo application' do
|
|
23
|
+
context 'sinatra' do
|
|
24
|
+
it 'runs' do
|
|
25
|
+
clone_application(
|
|
26
|
+
'https://github.com/mongoid/mongoid-demo',
|
|
27
|
+
subdir: 'sinatra-minimal',
|
|
28
|
+
) do
|
|
28
29
|
|
|
29
|
-
process = ChildProcess.build(*%w(bundle exec ruby app.rb))
|
|
30
|
-
process.environment.update(clean_env)
|
|
31
|
-
process.io.inherit!
|
|
32
|
-
process.start
|
|
33
|
-
|
|
34
|
-
begin
|
|
35
30
|
# JRuby needs a long timeout
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
uri = URI.parse('http://localhost:4567/posts')
|
|
40
|
-
resp = JSON.parse(uri.open.read)
|
|
41
|
-
ensure
|
|
42
|
-
Process.kill('TERM', process.pid)
|
|
43
|
-
status = process.wait
|
|
44
|
-
end
|
|
31
|
+
start_app(%w(bundle exec ruby app.rb), 4567, 40) do |port|
|
|
32
|
+
uri = URI.parse('http://localhost:4567/posts')
|
|
33
|
+
resp = JSON.parse(uri.open.read)
|
|
45
34
|
|
|
46
|
-
|
|
35
|
+
resp.should == []
|
|
47
36
|
|
|
48
|
-
|
|
37
|
+
end
|
|
38
|
+
end
|
|
49
39
|
end
|
|
50
40
|
end
|
|
51
|
-
end
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
subdir: 'rails-api',
|
|
60
|
-
rails_version: rails_version,
|
|
61
|
-
) do
|
|
62
|
-
|
|
63
|
-
process = ChildProcess.build(*%w(bundle exec rails s))
|
|
64
|
-
process.environment.update(clean_env)
|
|
65
|
-
process.io.inherit!
|
|
66
|
-
process.start
|
|
67
|
-
|
|
68
|
-
begin
|
|
69
|
-
# JRuby needs a long timeout
|
|
70
|
-
wait_for_port(3000, 30)
|
|
71
|
-
sleep 1
|
|
72
|
-
|
|
73
|
-
uri = URI.parse('http://localhost:3000/posts')
|
|
74
|
-
resp = JSON.parse(uri.open.read)
|
|
75
|
-
ensure
|
|
76
|
-
Process.kill('TERM', process.pid)
|
|
77
|
-
status = process.wait
|
|
78
|
-
end
|
|
42
|
+
context 'rails-api' do
|
|
43
|
+
it 'runs' do
|
|
44
|
+
clone_application(
|
|
45
|
+
'https://github.com/mongoid/mongoid-demo',
|
|
46
|
+
subdir: 'rails-api',
|
|
47
|
+
) do
|
|
79
48
|
|
|
80
|
-
|
|
49
|
+
# JRuby needs a long timeout
|
|
50
|
+
start_app(%w(bundle exec rails s), 3000, 50) do |port|
|
|
51
|
+
uri = URI.parse('http://localhost:3000/posts')
|
|
52
|
+
resp = JSON.parse(uri.open.read)
|
|
81
53
|
|
|
82
|
-
|
|
83
|
-
[0, 15, 143].should include(status)
|
|
54
|
+
resp.should == []
|
|
84
55
|
end
|
|
85
56
|
end
|
|
86
57
|
end
|
|
87
58
|
end
|
|
88
59
|
end
|
|
89
60
|
|
|
61
|
+
def start_app(cmd, port, timeout)
|
|
62
|
+
process = ChildProcess.build(*cmd)
|
|
63
|
+
process.environment.update(clean_env)
|
|
64
|
+
process.io.inherit!
|
|
65
|
+
process.start
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
wait_for_port(port, timeout, process)
|
|
69
|
+
sleep 1
|
|
70
|
+
|
|
71
|
+
rv = yield port
|
|
72
|
+
ensure
|
|
73
|
+
# The process may have already died (due to an error exit) -
|
|
74
|
+
# in this case killing it will raise an exception.
|
|
75
|
+
Process.kill('TERM', process.pid) rescue nil
|
|
76
|
+
status = process.wait
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Exit should be either success or SIGTERM
|
|
80
|
+
[0, 15, 128 + 15].should include(status)
|
|
81
|
+
|
|
82
|
+
rv
|
|
83
|
+
end
|
|
84
|
+
|
|
90
85
|
context 'new application - rails' do
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
it 'creates' do
|
|
87
|
+
install_rails
|
|
88
|
+
|
|
89
|
+
Dir.chdir(TMP_BASE) do
|
|
90
|
+
FileUtils.rm_rf('mongoid-test')
|
|
91
|
+
Mrss::ChildProcessHelper.check_call(%w(rails new mongoid-test --skip-spring --skip-active-record), env: clean_env)
|
|
92
|
+
|
|
93
|
+
Dir.chdir('mongoid-test') do
|
|
94
|
+
adjust_app_gemfile
|
|
95
|
+
Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
|
|
96
|
+
|
|
97
|
+
Mrss::ChildProcessHelper.check_call(%w(rails g model post), env: clean_env)
|
|
98
|
+
Mrss::ChildProcessHelper.check_call(%w(rails g model comment post:belongs_to), env: clean_env)
|
|
99
|
+
|
|
100
|
+
# https://jira.mongodb.org/browse/MONGOID-4885
|
|
101
|
+
comment_text = File.read('app/models/comment.rb')
|
|
102
|
+
comment_text.should =~ /belongs_to :post/
|
|
103
|
+
comment_text.should_not =~ /embedded_in :post/
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'generates Mongoid config' do
|
|
109
|
+
install_rails
|
|
110
|
+
|
|
111
|
+
Dir.chdir(TMP_BASE) do
|
|
112
|
+
FileUtils.rm_rf('mongoid-test-config')
|
|
113
|
+
Mrss::ChildProcessHelper.check_call(%w(rails new mongoid-test-config --skip-spring --skip-active-record), env: clean_env)
|
|
114
|
+
|
|
115
|
+
Dir.chdir('mongoid-test-config') do
|
|
116
|
+
adjust_app_gemfile
|
|
117
|
+
Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
|
|
118
|
+
|
|
119
|
+
mongoid_config_file = File.join(TMP_BASE,'mongoid-test-config/config/mongoid.yml')
|
|
120
|
+
|
|
121
|
+
File.exist?(mongoid_config_file).should be false
|
|
122
|
+
Mrss::ChildProcessHelper.check_call(%w(rails g mongoid:config), env: clean_env)
|
|
123
|
+
File.exist?(mongoid_config_file).should be true
|
|
124
|
+
|
|
125
|
+
config_text = File.read(mongoid_config_file)
|
|
126
|
+
config_text.should =~ /mongoid_test_config_development/
|
|
127
|
+
config_text.should =~ /mongoid_test_config_test/
|
|
114
128
|
end
|
|
115
129
|
end
|
|
116
130
|
end
|
|
117
131
|
end
|
|
118
132
|
|
|
133
|
+
def install_rails
|
|
134
|
+
Mrss::ChildProcessHelper.check_call(%w(gem uni rails -a))
|
|
135
|
+
if (rails_version = SpecConfig.instance.rails_version) == 'master'
|
|
136
|
+
else
|
|
137
|
+
Mrss::ChildProcessHelper.check_call(%w(gem install rails --no-document -v) + [rails_version])
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
119
141
|
context 'local test applications' do
|
|
120
142
|
let(:client) { Mongoid.default_client }
|
|
121
143
|
|
|
@@ -136,7 +158,7 @@ describe 'Mongoid application tests' do
|
|
|
136
158
|
before do
|
|
137
159
|
Dir.chdir(APP_PATH) do
|
|
138
160
|
remove_bundler_req
|
|
139
|
-
ChildProcessHelper.check_call(%w(bundle install), env: env)
|
|
161
|
+
Mrss::ChildProcessHelper.check_call(%w(bundle install), env: env)
|
|
140
162
|
write_mongoid_yml
|
|
141
163
|
end
|
|
142
164
|
|
|
@@ -150,7 +172,7 @@ describe 'Mongoid application tests' do
|
|
|
150
172
|
end
|
|
151
173
|
index.should be nil
|
|
152
174
|
|
|
153
|
-
ChildProcessHelper.check_call(%w(rake db:mongoid:create_indexes),
|
|
175
|
+
Mrss::ChildProcessHelper.check_call(%w(bundle exec rake db:mongoid:create_indexes),
|
|
154
176
|
cwd: APP_PATH, env: env)
|
|
155
177
|
|
|
156
178
|
index = client['posts'].indexes.detect do |index|
|
|
@@ -165,13 +187,14 @@ describe 'Mongoid application tests' do
|
|
|
165
187
|
end
|
|
166
188
|
end
|
|
167
189
|
|
|
168
|
-
def clone_application(repo_url, subdir: nil
|
|
190
|
+
def clone_application(repo_url, subdir: nil)
|
|
169
191
|
Dir.chdir(TMP_BASE) do
|
|
170
192
|
FileUtils.rm_rf(File.basename(repo_url))
|
|
171
|
-
ChildProcessHelper.check_call(%w(git clone) + [repo_url])
|
|
193
|
+
Mrss::ChildProcessHelper.check_call(%w(git clone) + [repo_url])
|
|
172
194
|
Dir.chdir(File.join(*[File.basename(repo_url), subdir].compact)) do
|
|
173
|
-
adjust_app_gemfile
|
|
174
|
-
|
|
195
|
+
adjust_app_gemfile
|
|
196
|
+
adjust_rails_defaults
|
|
197
|
+
Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
|
|
175
198
|
puts `git diff`
|
|
176
199
|
|
|
177
200
|
write_mongoid_yml
|
|
@@ -181,11 +204,44 @@ describe 'Mongoid application tests' do
|
|
|
181
204
|
end
|
|
182
205
|
end
|
|
183
206
|
|
|
207
|
+
def parse_mongodb_uri(uri)
|
|
208
|
+
pre, query = uri.split('?', 2)
|
|
209
|
+
if pre =~ %r,\A(mongodb(?:.*?))://([^/]+)(?:/(.*))?\z,
|
|
210
|
+
protocol = $1
|
|
211
|
+
hosts = $2
|
|
212
|
+
database = $3
|
|
213
|
+
if database == ''
|
|
214
|
+
database = nil
|
|
215
|
+
end
|
|
216
|
+
else
|
|
217
|
+
raise ArgumentError, "Invalid MongoDB URI: #{uri}"
|
|
218
|
+
end
|
|
219
|
+
if query == ''
|
|
220
|
+
query = nil
|
|
221
|
+
end
|
|
222
|
+
{
|
|
223
|
+
protocol: protocol,
|
|
224
|
+
hosts: hosts,
|
|
225
|
+
database: database,
|
|
226
|
+
query: query,
|
|
227
|
+
}
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def build_mongodb_uri(parts)
|
|
231
|
+
"#{parts.fetch(:protocol)}://#{parts.fetch(:hosts)}/#{parts[:database]}?#{parts[:query]}"
|
|
232
|
+
end
|
|
233
|
+
|
|
184
234
|
def write_mongoid_yml
|
|
235
|
+
# HACK: the driver does not provide a MongoDB URI parser and assembler,
|
|
236
|
+
# and the Ruby standard library URI module doesn't handle multiple hosts.
|
|
237
|
+
parts = parse_mongodb_uri(SpecConfig.instance.uri_str)
|
|
238
|
+
parts[:database] = 'mongoid_test'
|
|
239
|
+
uri = build_mongodb_uri(parts)
|
|
240
|
+
p uri
|
|
185
241
|
env_config = {'clients' => {'default' => {
|
|
186
242
|
# TODO massive hack, will fail if uri specifies a database name or
|
|
187
243
|
# any uri options
|
|
188
|
-
'uri' =>
|
|
244
|
+
'uri' => uri,
|
|
189
245
|
}}}
|
|
190
246
|
config = {'development' => env_config, 'production' => env_config}
|
|
191
247
|
File.open('config/mongoid.yml', 'w') do |f|
|
|
@@ -193,7 +249,7 @@ describe 'Mongoid application tests' do
|
|
|
193
249
|
end
|
|
194
250
|
end
|
|
195
251
|
|
|
196
|
-
def adjust_app_gemfile(rails_version:
|
|
252
|
+
def adjust_app_gemfile(rails_version: SpecConfig.instance.rails_version)
|
|
197
253
|
remove_bundler_req
|
|
198
254
|
|
|
199
255
|
gemfile_lines = IO.readlines('Gemfile')
|
|
@@ -205,13 +261,41 @@ describe 'Mongoid application tests' do
|
|
|
205
261
|
gemfile_lines.delete_if do |line|
|
|
206
262
|
line =~ /rails/
|
|
207
263
|
end
|
|
208
|
-
|
|
264
|
+
if rails_version == 'master'
|
|
265
|
+
gemfile_lines << "gem 'rails', git: 'https://github.com/rails/rails'\n"
|
|
266
|
+
else
|
|
267
|
+
gemfile_lines << "gem 'rails', '~> #{rails_version}.0'\n"
|
|
268
|
+
end
|
|
209
269
|
end
|
|
210
270
|
File.open('Gemfile', 'w') do |f|
|
|
211
271
|
f << gemfile_lines.join
|
|
212
272
|
end
|
|
213
273
|
end
|
|
214
274
|
|
|
275
|
+
def adjust_rails_defaults(rails_version: SpecConfig.instance.rails_version)
|
|
276
|
+
if File.exist?('config/application.rb')
|
|
277
|
+
lines = IO.readlines('config/application.rb')
|
|
278
|
+
lines.each do |line|
|
|
279
|
+
line.gsub!(/config.load_defaults \d\.\d/, "config.load_defaults #{rails_version}")
|
|
280
|
+
end
|
|
281
|
+
File.open('config/application.rb', 'w') do |f|
|
|
282
|
+
f << lines.join
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
if rails_version == '5.1'
|
|
287
|
+
secrets = {
|
|
288
|
+
'development' => {
|
|
289
|
+
'secret_key_base' => 'abracadabra',
|
|
290
|
+
'my_secret_token' => 'very_secret',
|
|
291
|
+
},
|
|
292
|
+
}
|
|
293
|
+
File.open('config/secrets.yml', 'w') do |f|
|
|
294
|
+
f << YAML.dump(secrets)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
215
299
|
def remove_bundler_req
|
|
216
300
|
lock_lines = IO.readlines('Gemfile.lock')
|
|
217
301
|
# Get rid of the bundled with line so that whatever bundler is installed
|
|
@@ -230,14 +314,14 @@ describe 'Mongoid application tests' do
|
|
|
230
314
|
# in `initialize': too long unix socket path (126bytes given but 108bytes max) (ArgumentError)
|
|
231
315
|
# Is it trying to create unix sockets in current directory?
|
|
232
316
|
# https://stackoverflow.com/questions/30302021/rails-runner-without-spring
|
|
233
|
-
ChildProcessHelper.check_call(%w(bin/spring binstub --remove --all), env: clean_env)
|
|
317
|
+
Mrss::ChildProcessHelper.check_call(%w(bin/spring binstub --remove --all), env: clean_env)
|
|
234
318
|
end
|
|
235
319
|
|
|
236
320
|
def clean_env
|
|
237
321
|
@clean_env ||= Hash[ENV.keys.grep(/BUNDLE|RUBYOPT/).map { |k| [k, nil ] }]
|
|
238
322
|
end
|
|
239
323
|
|
|
240
|
-
def wait_for_port(port, timeout)
|
|
324
|
+
def wait_for_port(port, timeout, process)
|
|
241
325
|
deadline = Time.now + timeout
|
|
242
326
|
loop do
|
|
243
327
|
begin
|
|
@@ -245,6 +329,9 @@ describe 'Mongoid application tests' do
|
|
|
245
329
|
return
|
|
246
330
|
end
|
|
247
331
|
rescue IOError, SystemCallError
|
|
332
|
+
unless process.alive?
|
|
333
|
+
raise "Process #{process} died while waiting for port #{port}"
|
|
334
|
+
end
|
|
248
335
|
if Time.now > deadline
|
|
249
336
|
raise
|
|
250
337
|
end
|