mongoid 3.0.23 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +253 -9
- data/LICENSE +1 -1
- data/README.md +4 -1
- data/lib/config/locales/en.yml +7 -6
- data/lib/mongoid.rb +18 -1
- data/lib/mongoid/atomic.rb +22 -20
- data/lib/mongoid/atomic/paths/embedded.rb +19 -5
- data/lib/mongoid/atomic/paths/root.rb +1 -1
- data/lib/mongoid/atomic/positionable.rb +73 -0
- data/lib/mongoid/attributes.rb +63 -1
- data/lib/mongoid/callbacks.rb +58 -4
- data/lib/mongoid/components.rb +8 -3
- data/lib/mongoid/config.rb +71 -23
- data/lib/mongoid/contextual.rb +2 -1
- data/lib/mongoid/contextual/aggregable/mongo.rb +27 -63
- data/lib/mongoid/contextual/atomic.rb +4 -3
- data/lib/mongoid/contextual/find_and_modify.rb +1 -1
- data/lib/mongoid/contextual/geo_near.rb +238 -0
- data/lib/mongoid/contextual/map_reduce.rb +12 -1
- data/lib/mongoid/contextual/memory.rb +36 -31
- data/lib/mongoid/contextual/mongo.rb +147 -91
- data/lib/mongoid/contextual/queryable.rb +25 -0
- data/lib/mongoid/copyable.rb +4 -1
- data/lib/mongoid/criteria.rb +23 -275
- data/lib/mongoid/criterion/findable.rb +179 -0
- data/lib/mongoid/criterion/modifiable.rb +191 -0
- data/lib/mongoid/criterion/scoping.rb +11 -6
- data/lib/mongoid/document.rb +7 -56
- data/lib/mongoid/equality.rb +66 -0
- data/lib/mongoid/errors/mongoid_error.rb +7 -3
- data/lib/mongoid/extensions/array.rb +13 -1
- data/lib/mongoid/extensions/date.rb +9 -2
- data/lib/mongoid/extensions/hash.rb +38 -2
- data/lib/mongoid/extensions/nil_class.rb +12 -0
- data/lib/mongoid/extensions/object.rb +24 -0
- data/lib/mongoid/extensions/string.rb +14 -2
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/fields.rb +49 -5
- data/lib/mongoid/fields/foreign_key.rb +12 -0
- data/lib/mongoid/fields/standard.rb +12 -0
- data/lib/mongoid/finders.rb +8 -0
- data/lib/mongoid/hierarchy.rb +19 -1
- data/lib/mongoid/indexes.rb +30 -4
- data/lib/mongoid/indexes/validators/options.rb +12 -2
- data/lib/mongoid/inspection.rb +2 -1
- data/lib/mongoid/matchers/strategies.rb +5 -5
- data/lib/mongoid/observer.rb +27 -36
- data/lib/mongoid/persistence.rb +42 -17
- data/lib/mongoid/persistence/atomic.rb +10 -5
- data/lib/mongoid/persistence/atomic/operation.rb +26 -9
- data/lib/mongoid/persistence/atomic/unset.rb +1 -1
- data/lib/mongoid/persistence/operations/embedded/insert.rb +5 -2
- data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -2
- data/lib/mongoid/persistence/operations/update.rb +7 -3
- data/lib/mongoid/railties/database.rake +12 -19
- data/lib/mongoid/relations.rb +2 -0
- data/lib/mongoid/relations/accessors.rb +30 -8
- data/lib/mongoid/relations/binding.rb +5 -1
- data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -3
- data/lib/mongoid/relations/counter_cache.rb +107 -0
- data/lib/mongoid/relations/embedded/batchable.rb +13 -4
- data/lib/mongoid/relations/embedded/many.rb +30 -1
- data/lib/mongoid/relations/macros.rb +2 -0
- data/lib/mongoid/relations/marshalable.rb +0 -1
- data/lib/mongoid/relations/metadata.rb +63 -11
- data/lib/mongoid/relations/options.rb +1 -0
- data/lib/mongoid/relations/proxy.rb +45 -2
- data/lib/mongoid/relations/referenced/in.rb +11 -2
- data/lib/mongoid/relations/referenced/many.rb +31 -3
- data/lib/mongoid/relations/referenced/many_to_many.rb +31 -3
- data/lib/mongoid/relations/referenced/one.rb +1 -1
- data/lib/mongoid/relations/targets/enumerable.rb +5 -1
- data/lib/mongoid/relations/touchable.rb +35 -6
- data/lib/mongoid/reloading.rb +5 -3
- data/lib/mongoid/scoping.rb +2 -2
- data/lib/mongoid/sessions.rb +57 -7
- data/lib/mongoid/sessions/factory.rb +22 -1
- data/lib/mongoid/threaded.rb +4 -30
- data/lib/mongoid/threaded/lifecycle.rb +12 -12
- data/lib/mongoid/timestamps.rb +1 -0
- data/lib/mongoid/timestamps/created.rb +2 -0
- data/lib/mongoid/timestamps/created/short.rb +19 -0
- data/lib/mongoid/timestamps/short.rb +10 -0
- data/lib/mongoid/timestamps/updated.rb +2 -0
- data/lib/mongoid/timestamps/updated/short.rb +19 -0
- data/lib/mongoid/validations.rb +2 -0
- data/lib/mongoid/validations/queryable.rb +2 -2
- data/lib/mongoid/validations/uniqueness.rb +1 -18
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/model/model_generator.rb +1 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +3 -0
- data/lib/rails/mongoid.rb +53 -29
- data/lib/support/ruby_version.rb +26 -0
- metadata +18 -7
@@ -16,7 +16,9 @@ module Mongoid
|
|
16
16
|
# false
|
17
17
|
# );
|
18
18
|
class Insert
|
19
|
-
include Insertion
|
19
|
+
include Insertion
|
20
|
+
include Operations
|
21
|
+
include Mongoid::Atomic::Positionable
|
20
22
|
|
21
23
|
# Insert the new document in the database. If the document's parent is a
|
22
24
|
# new record, we will call save on the parent, otherwise we will $push
|
@@ -32,7 +34,8 @@ module Mongoid
|
|
32
34
|
if parent.new_record?
|
33
35
|
parent.insert
|
34
36
|
else
|
35
|
-
|
37
|
+
selector = parent.atomic_selector
|
38
|
+
collection.find(selector).update(positionally(selector, inserts))
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
@@ -14,7 +14,9 @@ module Mongoid
|
|
14
14
|
# false
|
15
15
|
# );
|
16
16
|
class Remove
|
17
|
-
include Deletion
|
17
|
+
include Deletion
|
18
|
+
include Operations
|
19
|
+
include Mongoid::Atomic::Positionable
|
18
20
|
|
19
21
|
# Remove the document from the database. If the parent is a new record,
|
20
22
|
# it will get removed in Ruby only. If the parent is not a new record
|
@@ -29,7 +31,8 @@ module Mongoid
|
|
29
31
|
prepare do |doc|
|
30
32
|
parent.remove_child(doc) if notifying_parent?
|
31
33
|
if parent.persisted?
|
32
|
-
|
34
|
+
selector = parent.atomic_selector
|
35
|
+
collection.find(selector).update(positionally(selector, deletes))
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -30,7 +30,9 @@ module Mongoid
|
|
30
30
|
# );
|
31
31
|
#
|
32
32
|
class Update
|
33
|
-
include Modification
|
33
|
+
include Modification
|
34
|
+
include Operations
|
35
|
+
include Mongoid::Atomic::Positionable
|
34
36
|
|
35
37
|
# Persist the document that is to be updated to the database. This will
|
36
38
|
# only write changed fields via MongoDB's $set modifier operation.
|
@@ -42,9 +44,11 @@ module Mongoid
|
|
42
44
|
def persist
|
43
45
|
prepare do
|
44
46
|
unless updates.empty?
|
45
|
-
collection.find(selector).update(updates)
|
47
|
+
collection.find(selector).update(positionally(selector, updates))
|
46
48
|
conflicts.each_pair do |key, value|
|
47
|
-
collection.find(selector).update(
|
49
|
+
collection.find(selector).update(
|
50
|
+
positionally(selector, { key => value })
|
51
|
+
)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -5,6 +5,11 @@ namespace :db do
|
|
5
5
|
task :drop => "mongoid:drop"
|
6
6
|
end
|
7
7
|
|
8
|
+
unless Rake::Task.task_defined?("db:purge")
|
9
|
+
desc "Drop all collections except the system collections"
|
10
|
+
task :purge => "mongoid:purge"
|
11
|
+
end
|
12
|
+
|
8
13
|
unless Rake::Task.task_defined?("db:seed")
|
9
14
|
# if another ORM has defined db:seed, don"t run it twice.
|
10
15
|
desc "Load the seed data from db/seeds.rb"
|
@@ -61,36 +66,24 @@ namespace :db do
|
|
61
66
|
end
|
62
67
|
|
63
68
|
namespace :mongoid do
|
64
|
-
|
65
69
|
desc "Create the indexes defined on your mongoid models"
|
66
70
|
task :create_indexes => :environment do
|
67
|
-
|
68
|
-
engine.paths["app/models"].expanded
|
69
|
-
end
|
70
|
-
root_models_paths = Rails.application.paths["app/models"]
|
71
|
-
models_paths = engines_models_paths.push(root_models_paths).flatten
|
72
|
-
|
73
|
-
models_paths.each do |path|
|
74
|
-
::Rails::Mongoid.create_indexes("#{path}/**/*.rb")
|
75
|
-
end
|
71
|
+
::Rails::Mongoid.create_indexes
|
76
72
|
end
|
77
73
|
|
78
74
|
desc "Remove the indexes defined on your mongoid models without questions!"
|
79
75
|
task :remove_indexes => :environment do
|
80
|
-
|
81
|
-
engine.paths["app/models"].expanded
|
82
|
-
end
|
83
|
-
root_models_paths = Rails.application.paths["app/models"]
|
84
|
-
models_paths = engines_models_paths.push(root_models_paths).flatten
|
85
|
-
|
86
|
-
models_paths.each do |path|
|
87
|
-
::Rails::Mongoid.remove_indexes("#{path}/**/*.rb")
|
88
|
-
end
|
76
|
+
::Rails::Mongoid.remove_indexes
|
89
77
|
end
|
90
78
|
|
91
79
|
desc "Drops the database for the current Rails.env"
|
92
80
|
task :drop => :environment do
|
93
81
|
::Mongoid::Sessions.default.drop
|
94
82
|
end
|
83
|
+
|
84
|
+
desc "Drop all collections except the system collections"
|
85
|
+
task :purge => :environment do
|
86
|
+
::Mongoid.purge!
|
87
|
+
end
|
95
88
|
end
|
96
89
|
end
|
data/lib/mongoid/relations.rb
CHANGED
@@ -4,6 +4,7 @@ require "mongoid/relations/auto_save"
|
|
4
4
|
require "mongoid/relations/cascading"
|
5
5
|
require "mongoid/relations/constraint"
|
6
6
|
require "mongoid/relations/conversions"
|
7
|
+
require "mongoid/relations/counter_cache"
|
7
8
|
require "mongoid/relations/cyclic"
|
8
9
|
require "mongoid/relations/proxy"
|
9
10
|
require "mongoid/relations/bindings"
|
@@ -43,6 +44,7 @@ module Mongoid
|
|
43
44
|
include Reflections
|
44
45
|
include Synchronization
|
45
46
|
include Touchable
|
47
|
+
include CounterCache
|
46
48
|
|
47
49
|
attr_accessor :metadata
|
48
50
|
|
@@ -113,11 +113,7 @@ module Mongoid
|
|
113
113
|
else
|
114
114
|
_building do
|
115
115
|
_loading do
|
116
|
-
|
117
|
-
# we want to avoid an extra database query when we know it is not
|
118
|
-
# necessary.
|
119
|
-
key = (new_record? && _binding?) ? nil : attributes[metadata.key]
|
120
|
-
__build__(name, key, metadata)
|
116
|
+
__build__(name, attributes[metadata.key], metadata)
|
121
117
|
end
|
122
118
|
end
|
123
119
|
end
|
@@ -128,6 +124,30 @@ module Mongoid
|
|
128
124
|
end
|
129
125
|
end
|
130
126
|
|
127
|
+
# @todo: Durran: Refactor before release, but this fixes the issue with
|
128
|
+
# the extra queries.
|
129
|
+
def get_relation_for_set(name, metadata, object)
|
130
|
+
variable = "@#{name}"
|
131
|
+
value = if instance_variable_defined?(variable)
|
132
|
+
instance_variable_get(variable)
|
133
|
+
else
|
134
|
+
_building do
|
135
|
+
_loading do
|
136
|
+
if needs_no_database_query?(object, metadata)
|
137
|
+
__build__(name, object, metadata)
|
138
|
+
else
|
139
|
+
__build__(name, attributes[metadata.key], metadata)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def needs_no_database_query?(object, metadata)
|
147
|
+
object.is_a?(Document) && !object.embedded? &&
|
148
|
+
object.id == attributes[metadata.key]
|
149
|
+
end
|
150
|
+
|
131
151
|
# Is the current code executing without autobuild functionality?
|
132
152
|
#
|
133
153
|
# @example Is autobuild disabled?
|
@@ -151,10 +171,10 @@ module Mongoid
|
|
151
171
|
#
|
152
172
|
# @since 3.0.0
|
153
173
|
def without_autobuild
|
154
|
-
Threaded.
|
174
|
+
Threaded.begin_execution("without_autobuild")
|
155
175
|
yield
|
156
176
|
ensure
|
157
|
-
Threaded.
|
177
|
+
Threaded.exit_execution("without_autobuild")
|
158
178
|
end
|
159
179
|
|
160
180
|
module ClassMethods
|
@@ -241,8 +261,10 @@ module Mongoid
|
|
241
261
|
def setter(name, metadata)
|
242
262
|
re_define_method("#{name}=") do |object|
|
243
263
|
without_autobuild do
|
244
|
-
if metadata.many?
|
264
|
+
if metadata.many?
|
245
265
|
set_relation(name, get_relation(name, metadata).substitute(object.substitutable))
|
266
|
+
elsif value = get_relation_for_set(name, metadata, object)
|
267
|
+
set_relation(name, value.substitute(object.substitutable))
|
246
268
|
else
|
247
269
|
__build__(name, object.substitutable, metadata)
|
248
270
|
end
|
@@ -190,12 +190,16 @@ module Mongoid
|
|
190
190
|
# @since 3.0.0
|
191
191
|
def bind_from_relational_parent(doc)
|
192
192
|
check_inverse!(doc)
|
193
|
-
bind_foreign_key(doc, base
|
193
|
+
bind_foreign_key(doc, record_id(base))
|
194
194
|
bind_polymorphic_type(doc, base.class.name)
|
195
195
|
bind_inverse(doc, base)
|
196
196
|
bind_inverse_of_field(doc, metadata.name)
|
197
197
|
end
|
198
198
|
|
199
|
+
def record_id(base)
|
200
|
+
base.__send__(metadata.primary_key)
|
201
|
+
end
|
202
|
+
|
199
203
|
# Ensure that the metadata on the base is correct, for the cases
|
200
204
|
# where we have multiple belongs to definitions and were are setting
|
201
205
|
# different parents in memory in order.
|
@@ -21,7 +21,7 @@ module Mongoid
|
|
21
21
|
def bind_one
|
22
22
|
binding do
|
23
23
|
check_inverses!(target)
|
24
|
-
bind_foreign_key(base, target
|
24
|
+
bind_foreign_key(base, record_id(target))
|
25
25
|
bind_polymorphic_inverse_type(base, target.class.name)
|
26
26
|
if inverse = metadata.inverse(target)
|
27
27
|
if set_base_metadata
|
@@ -20,7 +20,7 @@ module Mongoid
|
|
20
20
|
binding do
|
21
21
|
inverse_keys = doc.you_must(metadata.inverse_foreign_key)
|
22
22
|
if inverse_keys
|
23
|
-
inverse_keys.push(base
|
23
|
+
inverse_keys.push(record_id(base))
|
24
24
|
doc.reset_relation_criteria(metadata.inverse)
|
25
25
|
end
|
26
26
|
base.synced[metadata.foreign_key] = true
|
@@ -36,10 +36,10 @@ module Mongoid
|
|
36
36
|
# @since 2.0.0.rc.1
|
37
37
|
def unbind_one(doc)
|
38
38
|
binding do
|
39
|
-
base.send(metadata.foreign_key).delete_one(doc
|
39
|
+
base.send(metadata.foreign_key).delete_one(record_id(doc))
|
40
40
|
inverse_keys = doc.you_must(metadata.inverse_foreign_key)
|
41
41
|
if inverse_keys
|
42
|
-
inverse_keys.delete_one(base
|
42
|
+
inverse_keys.delete_one(record_id(base))
|
43
43
|
doc.reset_relation_criteria(metadata.inverse)
|
44
44
|
end
|
45
45
|
base.synced[metadata.foreign_key] = true
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Relations
|
4
|
+
module CounterCache
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
# Reset the given counter using the .count() query from the
|
10
|
+
# db. This method is usuful in case that a counter got
|
11
|
+
# corrupted, or a new counter was added to the collection.
|
12
|
+
#
|
13
|
+
# @example Reset the given counter cache
|
14
|
+
# Post.reset_counters('50e0edd97c71c17ea9000001', :comments)
|
15
|
+
#
|
16
|
+
# @param [ String ] The id of the object that will be reset.
|
17
|
+
# @param [ Symbol, Array ] One or more counter caches to reset
|
18
|
+
#
|
19
|
+
# @since 3.1.0
|
20
|
+
def reset_counters(id, *counters)
|
21
|
+
object = find(id)
|
22
|
+
counters.each do |name|
|
23
|
+
meta = reflect_on_association(name)
|
24
|
+
inverse = meta.klass.reflect_on_association(meta.inverse)
|
25
|
+
counter_name = inverse.counter_cache_column_name
|
26
|
+
object.update_attribute(counter_name, object.send(name).count)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Update the given counters by the value factor. It uses the
|
31
|
+
# atomic $inc command.
|
32
|
+
#
|
33
|
+
# @example Add 5 to comments counter and remove 2 from likes
|
34
|
+
# counter.
|
35
|
+
# Post.update_counters('50e0edd97c71c17ea9000001',
|
36
|
+
# :comments_count => 5, :likes_count => -2)
|
37
|
+
#
|
38
|
+
# @param [ String ] The id of the object to update.
|
39
|
+
# @param [ Hash ] Key = counter_cahe and Value = factor.
|
40
|
+
#
|
41
|
+
# @since 3.1.0
|
42
|
+
def update_counters(id, counters)
|
43
|
+
counters.map do |key, value|
|
44
|
+
where(:_id => id).inc(key, value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Increment the counter name from the entries that match the
|
49
|
+
# id by one. This method is used on associations callbacks
|
50
|
+
# when counter_cache is enable
|
51
|
+
#
|
52
|
+
# @example Increment comments counter
|
53
|
+
# Post.increment_counter(:comments_count, '50e0edd97c71c17ea9000001')
|
54
|
+
#
|
55
|
+
# @param [ Symbol ] Counter cache name
|
56
|
+
# @param [ String ] The id of the object that will be reset.
|
57
|
+
#
|
58
|
+
# @since 3.1.0
|
59
|
+
def increment_counter(counter_name, id)
|
60
|
+
update_counters(id, counter_name.to_sym => 1)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Decrement the counter name from the entries that match the
|
64
|
+
# id by one. This method is used on associations callbacks
|
65
|
+
# when counter_cache is enable
|
66
|
+
#
|
67
|
+
# @example Decrement comments counter
|
68
|
+
# Post.decrement_counter(:comments_count, '50e0edd97c71c17ea9000001')
|
69
|
+
#
|
70
|
+
# @param [ Symbol ] Counter cache name
|
71
|
+
# @param [ String ] The id of the object that will be reset.
|
72
|
+
#
|
73
|
+
# @since 3.1.0
|
74
|
+
def decrement_counter(counter_name, id)
|
75
|
+
update_counters(id, counter_name.to_sym => -1)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Add the callbacks responsible for update the counter cache field
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
#
|
84
|
+
# @example Add the touchable.
|
85
|
+
# Person.add_counter_callbacks(meta)
|
86
|
+
#
|
87
|
+
# @param [ Metadata ] metadata The metadata for the relation.
|
88
|
+
#
|
89
|
+
# @since 3.1.0
|
90
|
+
def add_counter_cache_callbacks(meta)
|
91
|
+
name = meta.name
|
92
|
+
cache_column = meta.counter_cache_column_name.to_sym
|
93
|
+
|
94
|
+
after_create do
|
95
|
+
record = __send__(name)
|
96
|
+
record.class.increment_counter(cache_column, record.id) if record.try(:persisted?)
|
97
|
+
end
|
98
|
+
|
99
|
+
before_destroy do
|
100
|
+
record = __send__(name)
|
101
|
+
record.class.decrement_counter(cache_column, record.id) if record.try(:persisted?)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -6,6 +6,7 @@ module Mongoid
|
|
6
6
|
# Contains behaviour for executing operations in batch on embedded
|
7
7
|
# documents.
|
8
8
|
module Batchable
|
9
|
+
include Mongoid::Atomic::Positionable
|
9
10
|
|
10
11
|
# Insert new documents as a batch push ($pushAll). This ensures that
|
11
12
|
# all callbacks are run at the appropriate time and only 1 request is
|
@@ -36,7 +37,9 @@ module Mongoid
|
|
36
37
|
def batch_clear(docs)
|
37
38
|
pre_process_batch_remove(docs, :delete)
|
38
39
|
unless docs.empty?
|
39
|
-
collection.find(selector).update(
|
40
|
+
collection.find(selector).update(
|
41
|
+
positionally(selector, "$unset" => { path => true })
|
42
|
+
)
|
40
43
|
post_process_batch_remove(docs, :delete)
|
41
44
|
end
|
42
45
|
_unscoped.clear
|
@@ -53,8 +56,10 @@ module Mongoid
|
|
53
56
|
# @since 3.0.0
|
54
57
|
def batch_remove(docs, method = :delete)
|
55
58
|
removals = pre_process_batch_remove(docs, method)
|
56
|
-
if !docs.empty?
|
57
|
-
collection.find(selector).update(
|
59
|
+
if !docs.empty? && !_assigning?
|
60
|
+
collection.find(selector).update(
|
61
|
+
positionally(selector, "$pullAll" => { path => removals })
|
62
|
+
)
|
58
63
|
post_process_batch_remove(docs, method)
|
59
64
|
end
|
60
65
|
Threaded.clear_options!
|
@@ -126,7 +131,9 @@ module Mongoid
|
|
126
131
|
self.inserts_valid = true
|
127
132
|
inserts = pre_process_batch_insert(docs)
|
128
133
|
if insertable?
|
129
|
-
collection.find(selector).update(
|
134
|
+
collection.find(selector).update(
|
135
|
+
positionally(selector, operation => { path => inserts })
|
136
|
+
)
|
130
137
|
post_process_batch_insert(docs)
|
131
138
|
end
|
132
139
|
inserts
|
@@ -289,6 +296,7 @@ module Mongoid
|
|
289
296
|
def pre_process_batch_remove(docs, method)
|
290
297
|
docs.map do |doc|
|
291
298
|
self.path = doc.atomic_path unless path
|
299
|
+
execute_callback :before_remove, doc
|
292
300
|
if !_assigning? && !metadata.versioned?
|
293
301
|
doc.cascade!
|
294
302
|
doc.run_before_callbacks(:destroy) if method == :destroy
|
@@ -296,6 +304,7 @@ module Mongoid
|
|
296
304
|
target.delete_one(doc)
|
297
305
|
_unscoped.delete_one(doc)
|
298
306
|
unbind_one(doc)
|
307
|
+
execute_callback :after_remove, doc
|
299
308
|
doc.as_document
|
300
309
|
end
|
301
310
|
end
|
@@ -130,6 +130,7 @@ module Mongoid
|
|
130
130
|
#
|
131
131
|
# @since 2.0.0.rc.1
|
132
132
|
def delete(document)
|
133
|
+
execute_callback :before_remove, document
|
133
134
|
doc = target.delete_one(document)
|
134
135
|
if doc && !_binding?
|
135
136
|
_unscoped.delete_one(doc) unless doc.paranoid?
|
@@ -145,6 +146,7 @@ module Mongoid
|
|
145
146
|
end
|
146
147
|
end
|
147
148
|
reindex
|
149
|
+
execute_callback :after_remove, document
|
148
150
|
doc
|
149
151
|
end
|
150
152
|
|
@@ -175,6 +177,28 @@ module Mongoid
|
|
175
177
|
remove_all(conditions, :delete)
|
176
178
|
end
|
177
179
|
|
180
|
+
# Delete all the documents for which the provided block returns true.
|
181
|
+
#
|
182
|
+
# @example Delete the matching documents.
|
183
|
+
# person.addresses.delete_if do |doc|
|
184
|
+
# doc.state = "GA"
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# @return [ Many, Enumerator ] The relation or an enumerator if no
|
188
|
+
# block was provided.
|
189
|
+
#
|
190
|
+
# @since 3.1.0
|
191
|
+
def delete_if
|
192
|
+
if block_given?
|
193
|
+
target.each do |doc|
|
194
|
+
delete(doc) if yield(doc)
|
195
|
+
end
|
196
|
+
self
|
197
|
+
else
|
198
|
+
super
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
178
202
|
# Destroy all the documents in the association whilst running callbacks.
|
179
203
|
#
|
180
204
|
# @example Destroy all documents from the relation.
|
@@ -318,10 +342,12 @@ module Mongoid
|
|
318
342
|
#
|
319
343
|
# @since 2.0.0.rc.1
|
320
344
|
def append(document)
|
345
|
+
execute_callback :before_add, document
|
321
346
|
target.push(*scope([document]))
|
322
347
|
_unscoped.push(document)
|
323
348
|
integrate(document)
|
324
349
|
document._index = _unscoped.size - 1
|
350
|
+
execute_callback :after_add, document
|
325
351
|
end
|
326
352
|
|
327
353
|
# Instantiate the binding associated with this relation.
|
@@ -608,7 +634,10 @@ module Mongoid
|
|
608
634
|
#
|
609
635
|
# @since 2.1.0
|
610
636
|
def valid_options
|
611
|
-
[
|
637
|
+
[
|
638
|
+
:as, :cascade_callbacks, :cyclic, :order, :versioned, :store_as,
|
639
|
+
:before_add, :after_add, :before_remove, :after_remove
|
640
|
+
]
|
612
641
|
end
|
613
642
|
|
614
643
|
# Get the default validation setting for the relation. Determines if
|