mongoid 2.0.0.beta.10 → 2.0.0.beta.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongoid.rb +3 -1
- data/lib/mongoid/associations.rb +16 -6
- data/lib/mongoid/associations/options.rb +5 -0
- data/lib/mongoid/components.rb +2 -0
- data/lib/mongoid/config.rb +1 -39
- data/lib/mongoid/criterion/optional.rb +36 -3
- data/lib/mongoid/document.rb +7 -22
- data/lib/mongoid/identity.rb +1 -1
- data/lib/mongoid/keys.rb +77 -0
- data/lib/mongoid/persistence.rb +14 -25
- data/lib/mongoid/persistence/command.rb +17 -5
- data/lib/mongoid/persistence/insert.rb +4 -1
- data/lib/mongoid/persistence/remove.rb +4 -1
- data/lib/mongoid/persistence/update.rb +5 -2
- data/lib/mongoid/safety.rb +168 -0
- data/lib/mongoid/version.rb +1 -1
- metadata +6 -4
data/lib/mongoid.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# Copyright (c) 2009 Durran Jordan
|
2
|
+
# Copyright (c) 2009, 2010 Durran Jordan
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -63,12 +63,14 @@ require "mongoid/hierarchy"
|
|
63
63
|
require "mongoid/identity"
|
64
64
|
require "mongoid/indexes"
|
65
65
|
require "mongoid/javascript"
|
66
|
+
require "mongoid/keys"
|
66
67
|
require "mongoid/logger"
|
67
68
|
require "mongoid/matchers"
|
68
69
|
require "mongoid/memoization"
|
69
70
|
require "mongoid/named_scope"
|
70
71
|
require "mongoid/paths"
|
71
72
|
require "mongoid/persistence"
|
73
|
+
require "mongoid/safety"
|
72
74
|
require "mongoid/scope"
|
73
75
|
require "mongoid/state"
|
74
76
|
require "mongoid/timestamps"
|
data/lib/mongoid/associations.rb
CHANGED
@@ -99,7 +99,9 @@ module Mongoid # :nodoc:
|
|
99
99
|
# end
|
100
100
|
def embedded_in(name, options = {}, &block)
|
101
101
|
unless options.has_key?(:inverse_of)
|
102
|
-
raise Errors::InvalidOptions.new(
|
102
|
+
raise Errors::InvalidOptions.new(
|
103
|
+
"Options for embedded_in association must include :inverse_of"
|
104
|
+
)
|
103
105
|
end
|
104
106
|
self.embedded = true
|
105
107
|
associate(Associations::EmbeddedIn, optionize(name, options, nil, &block))
|
@@ -176,8 +178,8 @@ module Mongoid # :nodoc:
|
|
176
178
|
def referenced_in(name, options = {}, &block)
|
177
179
|
opts = optionize(name, options, constraint(name, options, :in), &block)
|
178
180
|
associate(Associations::ReferencedIn, opts)
|
179
|
-
field(opts.foreign_key, :type =>
|
180
|
-
index(opts.foreign_key)
|
181
|
+
field(opts.foreign_key, :type => using_object_ids? ? BSON::ObjectID : String)
|
182
|
+
index(opts.foreign_key, :background => true) if !embedded? && opts.index
|
181
183
|
set_callback(:save, :before) { |document| document.update_foreign_keys }
|
182
184
|
end
|
183
185
|
|
@@ -268,7 +270,11 @@ module Mongoid # :nodoc:
|
|
268
270
|
define_method("build_#{name}") do |*params|
|
269
271
|
attrs = params[0]
|
270
272
|
attr_options = params[1] || {}
|
271
|
-
reset(name)
|
273
|
+
reset(name) do
|
274
|
+
unless type == Associations::EmbedsOne && attr_options[:update_only]
|
275
|
+
type.new(self, (attrs || {}).stringify_keys, options)
|
276
|
+
end
|
277
|
+
end
|
272
278
|
end
|
273
279
|
end
|
274
280
|
|
@@ -279,7 +285,9 @@ module Mongoid # :nodoc:
|
|
279
285
|
define_method("create_#{name}") do |*params|
|
280
286
|
attrs = params[0]
|
281
287
|
attr_options = params[1] || {}
|
282
|
-
|
288
|
+
unless type == Associations::EmbedsOne && attr_options[:update_only]
|
289
|
+
send("build_#{name}", attrs, attr_options).tap(&:save)
|
290
|
+
end
|
283
291
|
end
|
284
292
|
end
|
285
293
|
|
@@ -292,8 +300,10 @@ module Mongoid # :nodoc:
|
|
292
300
|
|
293
301
|
def reference_many(name, options, &block)
|
294
302
|
if (options[:stored_as] == :array)
|
303
|
+
foreign_key = "#{name.to_s.singularize}_ids"
|
295
304
|
opts = optionize(name, options, constraint(name, options, :many_as_array), &block)
|
296
|
-
field
|
305
|
+
field(foreign_key, :type => Array, :default => [])
|
306
|
+
index(foreign_key, :background => true) if opts.index
|
297
307
|
associate(Associations::ReferencesManyAsArray, opts)
|
298
308
|
else
|
299
309
|
opts = optionize(name, options, constraint(name, options, :many), &block)
|
data/lib/mongoid/components.rb
CHANGED
@@ -19,10 +19,12 @@ module Mongoid #:nodoc
|
|
19
19
|
include Mongoid::Fields
|
20
20
|
include Mongoid::Hierarchy
|
21
21
|
include Mongoid::Indexes
|
22
|
+
include Mongoid::Keys
|
22
23
|
include Mongoid::Matchers
|
23
24
|
include Mongoid::Memoization
|
24
25
|
include Mongoid::Paths
|
25
26
|
include Mongoid::Persistence
|
27
|
+
include Mongoid::Safety
|
26
28
|
include Mongoid::State
|
27
29
|
include Mongoid::Validations
|
28
30
|
include Mongoid::Callbacks
|
data/lib/mongoid/config.rb
CHANGED
@@ -12,7 +12,6 @@ module Mongoid #:nodoc
|
|
12
12
|
:persist_in_safe_mode,
|
13
13
|
:raise_not_found_error,
|
14
14
|
:autocreate_indexes,
|
15
|
-
:use_object_ids,
|
16
15
|
:skip_version_check
|
17
16
|
|
18
17
|
# Initializes the configuration with default settings.
|
@@ -195,51 +194,14 @@ module Mongoid #:nodoc
|
|
195
194
|
def reset
|
196
195
|
@allow_dynamic_fields = true
|
197
196
|
@parameterize_keys = true
|
198
|
-
@persist_in_safe_mode =
|
197
|
+
@persist_in_safe_mode = false
|
199
198
|
@raise_not_found_error = true
|
200
199
|
@reconnect_time = 3
|
201
200
|
@autocreate_indexes = false
|
202
|
-
@use_object_ids = false
|
203
201
|
@skip_version_check = false
|
204
202
|
@time_zone = nil
|
205
203
|
end
|
206
204
|
|
207
|
-
##
|
208
|
-
# If Mongoid.use_object_ids = true
|
209
|
-
# Convert args to BSON::ObjectID
|
210
|
-
# If this args is an array, convert all args inside
|
211
|
-
# Else
|
212
|
-
# return args
|
213
|
-
#
|
214
|
-
# Options:
|
215
|
-
#
|
216
|
-
# args : A +String+ or an +Array+ convert to +BSON::ObjectID+
|
217
|
-
# cast : A +Boolean+ define if we can or not cast to BSON::ObjectID. If false, we use the default type of args
|
218
|
-
#
|
219
|
-
# Example:
|
220
|
-
#
|
221
|
-
# <tt>Mongoid.convert_to_object_id("4ab2bc4b8ad548971900005c", true)</tt>
|
222
|
-
# <tt>Mongoid.convert_to_object_id(["4ab2bc4b8ad548971900005c", "4ab2bc4b8ad548971900005d"])</tt>
|
223
|
-
#
|
224
|
-
# Returns:
|
225
|
-
#
|
226
|
-
# If Mongoid.use_object_ids = true
|
227
|
-
# An +Array+ of +BSON::ObjectID+ of each element if params is an +Array+
|
228
|
-
# A +BSON::ObjectID+ from params if params is +String+
|
229
|
-
# Else
|
230
|
-
# <tt>args</tt>
|
231
|
-
#
|
232
|
-
def convert_to_object_id(args, cast=true)
|
233
|
-
return args if !use_object_ids || args.is_a?(BSON::ObjectID) || !cast
|
234
|
-
if args.is_a?(String)
|
235
|
-
BSON::ObjectID(args)
|
236
|
-
else
|
237
|
-
args.map{ |a|
|
238
|
-
a.is_a?(BSON::ObjectID) ? a : BSON::ObjectID(a)
|
239
|
-
}
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
205
|
protected
|
244
206
|
|
245
207
|
# Check if the database is valid and the correct version.
|
@@ -38,6 +38,38 @@ module Mongoid #:nodoc:
|
|
38
38
|
@options[:cache] == true
|
39
39
|
end
|
40
40
|
|
41
|
+
# If the document is using BSON::ObjectIDs the convert the argument to
|
42
|
+
# either an object id or an array of them if the supplied argument is an
|
43
|
+
# Array. Otherwise just return.
|
44
|
+
#
|
45
|
+
# Options:
|
46
|
+
# args: A +String+ or an +Array+ convert to +BSON::ObjectID+
|
47
|
+
# cast: A +Boolean+ define if we can or not cast to BSON::ObjectID.
|
48
|
+
# If false, we use the default type of args
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
#
|
52
|
+
# <tt>Mongoid.cast_ids!("4ab2bc4b8ad548971900005c", true)</tt>
|
53
|
+
# <tt>Mongoid.cast_ids!(["4ab2bc4b8ad548971900005c"])</tt>
|
54
|
+
#
|
55
|
+
# Returns:
|
56
|
+
#
|
57
|
+
# If using object ids:
|
58
|
+
# An +Array+ of +BSON::ObjectID+ of each element if params is an +Array+
|
59
|
+
# A +BSON::ObjectID+ from params if params is +String+
|
60
|
+
# Otherwise:
|
61
|
+
# <tt>args</tt>
|
62
|
+
def cast_ids!(args, cast = true)
|
63
|
+
return args if !using_object_ids? || args.is_a?(BSON::ObjectID) || !cast
|
64
|
+
if args.is_a?(String)
|
65
|
+
BSON::ObjectID(args)
|
66
|
+
else
|
67
|
+
args.map{ |a|
|
68
|
+
a.is_a?(BSON::ObjectID) ? a : BSON::ObjectID(a)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
41
73
|
# Adds fields to be sorted in descending order. Will add them in the order
|
42
74
|
# they were passed into the method.
|
43
75
|
#
|
@@ -102,9 +134,9 @@ module Mongoid #:nodoc:
|
|
102
134
|
def id(*ids)
|
103
135
|
ids.flatten!
|
104
136
|
if ids.size > 1
|
105
|
-
self.in(:_id =>
|
137
|
+
self.in(:_id => cast_ids!(ids, self.klass.primary_key.nil?))
|
106
138
|
else
|
107
|
-
@selector[:_id] =
|
139
|
+
@selector[:_id] = cast_ids!(ids.first, self.klass.primary_key.nil?)
|
108
140
|
end
|
109
141
|
self
|
110
142
|
end
|
@@ -174,7 +206,8 @@ module Mongoid #:nodoc:
|
|
174
206
|
@options[:skip] = value; self
|
175
207
|
end
|
176
208
|
|
177
|
-
# Adds a criterion to the +Criteria+ that specifies a type or an Array of
|
209
|
+
# Adds a criterion to the +Criteria+ that specifies a type or an Array of
|
210
|
+
# type that must be matched.
|
178
211
|
#
|
179
212
|
# Options:
|
180
213
|
#
|
data/lib/mongoid/document.rb
CHANGED
@@ -5,13 +5,9 @@ module Mongoid #:nodoc:
|
|
5
5
|
included do
|
6
6
|
include Mongoid::Components
|
7
7
|
|
8
|
-
cattr_accessor :primary_key
|
9
|
-
|
10
8
|
attr_accessor :association_name
|
11
9
|
attr_reader :new_record
|
12
10
|
|
13
|
-
delegate :primary_key, :to => "self.class"
|
14
|
-
|
15
11
|
unless self.instance_of?(Class) and self.name == ""
|
16
12
|
(@@descendants ||= {})[self] = :seen
|
17
13
|
end
|
@@ -46,22 +42,6 @@ module Mongoid #:nodoc:
|
|
46
42
|
end
|
47
43
|
end
|
48
44
|
|
49
|
-
# Defines the field that will be used for the id of this +Document+. This
|
50
|
-
# set the id of this +Document+ before save to a parameterized version of
|
51
|
-
# the field that was supplied. This is good for use for readable URLS in
|
52
|
-
# web applications.
|
53
|
-
#
|
54
|
-
# Example:
|
55
|
-
#
|
56
|
-
# class Person
|
57
|
-
# include Mongoid::Document
|
58
|
-
# key :first_name, :last_name
|
59
|
-
# end
|
60
|
-
def key(*fields)
|
61
|
-
self.primary_key = fields
|
62
|
-
set_callback :save, :before, :identify
|
63
|
-
end
|
64
|
-
|
65
45
|
# Returns the classes that have included Mongoid::Document
|
66
46
|
def self.descendents
|
67
47
|
(@@descendants ||= {}).keys
|
@@ -88,8 +68,13 @@ module Mongoid #:nodoc:
|
|
88
68
|
self == (comparison_object)
|
89
69
|
end
|
90
70
|
|
91
|
-
# Delegates to id in order to allow two records of the same type and id to
|
92
|
-
#
|
71
|
+
# Delegates to id in order to allow two records of the same type and id to
|
72
|
+
# work with something like:
|
73
|
+
# [ Person.find(1),
|
74
|
+
# Person.find(2),
|
75
|
+
# Person.find(3) ] &
|
76
|
+
# [ Person.find(1),
|
77
|
+
# Person.find(4) ] # => [ Person.find(1) ]
|
93
78
|
def hash
|
94
79
|
id.hash
|
95
80
|
end
|
data/lib/mongoid/identity.rb
CHANGED
data/lib/mongoid/keys.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Keys
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
cattr_accessor :primary_key, :_identity
|
7
|
+
self._identity = { :type => BSON::ObjectID }
|
8
|
+
|
9
|
+
delegate \
|
10
|
+
:_id_type,
|
11
|
+
:primary_key,
|
12
|
+
:using_object_ids?, :to => "self.class"
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods #:nodoc:
|
16
|
+
|
17
|
+
# Convenience method for returning the type of the id for this class.
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
#
|
21
|
+
# <tt>Person._id_type</tt>
|
22
|
+
#
|
23
|
+
# Returns:
|
24
|
+
#
|
25
|
+
# The type of the id.
|
26
|
+
def _id_type
|
27
|
+
_identity[:type]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Used for telling Mongoid on a per model basis whether to override the
|
31
|
+
# default +BSON::ObjectID+ and use a different type. This will be
|
32
|
+
# expanded in the future for requiring a PkFactory if the type is not a
|
33
|
+
# +BSON::ObjectID+ or +String+.
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
#
|
37
|
+
# class Person
|
38
|
+
# include Mongoid::Document
|
39
|
+
# identity :type => String
|
40
|
+
# end
|
41
|
+
def identity(options = {})
|
42
|
+
self._identity = options
|
43
|
+
end
|
44
|
+
|
45
|
+
# Defines the field that will be used for the id of this +Document+. This
|
46
|
+
# set the id of this +Document+ before save to a parameterized version of
|
47
|
+
# the field that was supplied. This is good for use for readable URLS in
|
48
|
+
# web applications.
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
#
|
52
|
+
# class Person
|
53
|
+
# include Mongoid::Document
|
54
|
+
# key :first_name, :last_name
|
55
|
+
# end
|
56
|
+
def key(*fields)
|
57
|
+
self.primary_key = fields
|
58
|
+
identity(:type => String)
|
59
|
+
set_callback :save, :before, :identify
|
60
|
+
end
|
61
|
+
|
62
|
+
# Convenience method for determining if we are using +BSON::ObjectIDs+ as
|
63
|
+
# our id.
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
#
|
67
|
+
# <tt>person.using_object_ids?</tt>
|
68
|
+
#
|
69
|
+
# Returns:
|
70
|
+
#
|
71
|
+
# true if we are using BSON::ObjectIDs
|
72
|
+
def using_object_ids?
|
73
|
+
_id_type == BSON::ObjectID
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -19,15 +19,14 @@ module Mongoid #:nodoc:
|
|
19
19
|
# <tt>document.upsert</tt>
|
20
20
|
module Persistence
|
21
21
|
extend ActiveSupport::Concern
|
22
|
+
|
22
23
|
# Remove the +Document+ from the datbase with callbacks.
|
23
24
|
#
|
24
25
|
# Example:
|
25
26
|
#
|
26
27
|
# <tt>document.destroy</tt>
|
27
|
-
|
28
|
-
|
29
|
-
def destroy
|
30
|
-
run_callbacks(:destroy) { self.destroyed = true if _remove }
|
28
|
+
def destroy(options = {})
|
29
|
+
run_callbacks(:destroy) { self.destroyed = true if _remove(options) }
|
31
30
|
end
|
32
31
|
|
33
32
|
# Insert a new +Document+ into the database. Will return the document
|
@@ -36,8 +35,8 @@ module Mongoid #:nodoc:
|
|
36
35
|
# Example:
|
37
36
|
#
|
38
37
|
# <tt>document.insert</tt>
|
39
|
-
def insert(
|
40
|
-
Insert.new(self,
|
38
|
+
def insert(options = {})
|
39
|
+
Insert.new(self, options).persist
|
41
40
|
end
|
42
41
|
|
43
42
|
# Remove the +Document+ from the datbase.
|
@@ -47,8 +46,8 @@ module Mongoid #:nodoc:
|
|
47
46
|
# <tt>document._remove</tt>
|
48
47
|
#
|
49
48
|
# TODO: Will get rid of other #remove once observable pattern killed.
|
50
|
-
def _remove
|
51
|
-
Remove.new(self).persist
|
49
|
+
def _remove(options = {})
|
50
|
+
Remove.new(self, options).persist
|
52
51
|
end
|
53
52
|
|
54
53
|
alias :delete :_remove
|
@@ -64,7 +63,7 @@ module Mongoid #:nodoc:
|
|
64
63
|
# Returns:
|
65
64
|
#
|
66
65
|
# +true+ if validation passed, will raise error otherwise.
|
67
|
-
def save!
|
66
|
+
def save!(options = {})
|
68
67
|
self.class.fail_validate!(self) unless upsert; true
|
69
68
|
end
|
70
69
|
|
@@ -73,8 +72,8 @@ module Mongoid #:nodoc:
|
|
73
72
|
# Example:
|
74
73
|
#
|
75
74
|
# <tt>document.update</tt>
|
76
|
-
def update(
|
77
|
-
Update.new(self,
|
75
|
+
def update(options = {})
|
76
|
+
Update.new(self, options).persist
|
78
77
|
end
|
79
78
|
|
80
79
|
# Update the +Document+ attributes in the datbase.
|
@@ -116,12 +115,11 @@ module Mongoid #:nodoc:
|
|
116
115
|
# Returns:
|
117
116
|
#
|
118
117
|
# A +Boolean+ for updates.
|
119
|
-
def upsert(
|
120
|
-
validate = parse_validate(validate)
|
118
|
+
def upsert(options = {})
|
121
119
|
if new_record?
|
122
|
-
insert(
|
120
|
+
insert(options).persisted?
|
123
121
|
else
|
124
|
-
update(
|
122
|
+
update(options)
|
125
123
|
end
|
126
124
|
end
|
127
125
|
|
@@ -133,15 +131,6 @@ module Mongoid #:nodoc:
|
|
133
131
|
# <tt>document.save</tt>
|
134
132
|
alias :save :upsert
|
135
133
|
|
136
|
-
protected
|
137
|
-
# Alternative validation params.
|
138
|
-
def parse_validate(validate)
|
139
|
-
if validate.is_a?(Hash) && validate.has_key?(:validate)
|
140
|
-
validate = validate[:validate]
|
141
|
-
end
|
142
|
-
validate
|
143
|
-
end
|
144
|
-
|
145
134
|
module ClassMethods #:nodoc:
|
146
135
|
|
147
136
|
# Create a new +Document+. This will instantiate a new document and
|
@@ -186,7 +175,7 @@ module Mongoid #:nodoc:
|
|
186
175
|
def delete_all(conditions = {})
|
187
176
|
RemoveAll.new(
|
188
177
|
self,
|
189
|
-
false,
|
178
|
+
{ :validate => false },
|
190
179
|
conditions[:conditions] || {}
|
191
180
|
).persist
|
192
181
|
end
|
@@ -17,13 +17,13 @@ module Mongoid #:nodoc:
|
|
17
17
|
# Options:
|
18
18
|
#
|
19
19
|
# document_or_class: The +Document+ or +Class+ to get the collection.
|
20
|
-
#
|
20
|
+
# options: Options like validation or safe mode.
|
21
21
|
# selector: Optional selector to use in query.
|
22
22
|
#
|
23
23
|
# Example:
|
24
24
|
#
|
25
|
-
# <tt>DeleteAll.new(Person,
|
26
|
-
def initialize(document_or_class,
|
25
|
+
# <tt>DeleteAll.new(Person, { :validate => true }, {})</tt>
|
26
|
+
def initialize(document_or_class, options = {}, selector = {})
|
27
27
|
if document_or_class.is_a?(Mongoid::Document)
|
28
28
|
@document = document_or_class
|
29
29
|
@collection = @document.embedded? ? @document._root.collection : @document.collection
|
@@ -31,8 +31,20 @@ module Mongoid #:nodoc:
|
|
31
31
|
@klass = document_or_class
|
32
32
|
@collection = @klass.collection
|
33
33
|
end
|
34
|
-
|
35
|
-
@
|
34
|
+
validate = options[:validate]
|
35
|
+
@selector = selector
|
36
|
+
@validate = (validate.nil? ? true : validate)
|
37
|
+
@options = { :safe => safe_mode?(options) }
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
# Determine based on configuration if we are persisting in safe mode or
|
42
|
+
# not.
|
43
|
+
#
|
44
|
+
# The query option will always override the global configuration.
|
45
|
+
def safe_mode?(options)
|
46
|
+
safe = options[:safe]
|
47
|
+
safe.nil? ? Mongoid.persist_in_safe_mode : safe
|
36
48
|
end
|
37
49
|
end
|
38
50
|
end
|
@@ -38,7 +38,10 @@ module Mongoid #:nodoc:
|
|
38
38
|
# Insert the document into the database.
|
39
39
|
def insert
|
40
40
|
if @document.embedded?
|
41
|
-
Persistence::InsertEmbedded.new(
|
41
|
+
Persistence::InsertEmbedded.new(
|
42
|
+
@document,
|
43
|
+
@options.merge(:validate => @validate)
|
44
|
+
).persist
|
42
45
|
else
|
43
46
|
@collection.insert(@document.raw_attributes, @options)
|
44
47
|
end
|
@@ -29,7 +29,10 @@ module Mongoid #:nodoc:
|
|
29
29
|
# Remove the document from the database.
|
30
30
|
def remove
|
31
31
|
if @document.embedded?
|
32
|
-
Persistence::RemoveEmbedded.new(
|
32
|
+
Persistence::RemoveEmbedded.new(
|
33
|
+
@document,
|
34
|
+
@options.merge(:validate => @validate)
|
35
|
+
).persist
|
33
36
|
else
|
34
37
|
@collection.remove({ :_id => @document.id }, @options)
|
35
38
|
end
|
@@ -61,9 +61,12 @@ module Mongoid #:nodoc:
|
|
61
61
|
updates = @document._updates
|
62
62
|
unless updates.empty?
|
63
63
|
other_pushes = updates.delete(:other)
|
64
|
-
|
65
64
|
@collection.update(@document._selector, updates, @options.merge(:multi => false))
|
66
|
-
@collection.update(
|
65
|
+
@collection.update(
|
66
|
+
@document._selector,
|
67
|
+
{ "$pushAll" => other_pushes },
|
68
|
+
@options.merge(:multi => false)
|
69
|
+
) if other_pushes
|
67
70
|
end; true
|
68
71
|
end
|
69
72
|
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
|
4
|
+
# The +Safety+ module is used to provide a DSL to execute database operations
|
5
|
+
# in safe mode on a per query basis, either from the +Document+ class level
|
6
|
+
# or instance level.
|
7
|
+
module Safety
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Execute the following class-level persistence operation in safe mode.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# <tt>person.safely.upsert</tt>
|
15
|
+
# <tt>person.safely.destroy</tt>
|
16
|
+
#
|
17
|
+
# Returns:
|
18
|
+
#
|
19
|
+
# A +Proxy+ to the +Document+.
|
20
|
+
def safely
|
21
|
+
Proxy.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods #:nodoc:
|
25
|
+
|
26
|
+
# Execute the following class-level persistence operation in safe mode.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# <tt>Person.safely.create(:name => "John")</tt>
|
31
|
+
# <tt>Person.safely.delete_all</tt>
|
32
|
+
#
|
33
|
+
# Returns:
|
34
|
+
#
|
35
|
+
# A +Proxy+ to the +Document+ class.
|
36
|
+
def safely
|
37
|
+
Proxy.new(self)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# When this class proxies a document or class, the next persistence
|
42
|
+
# operation executed on it will query in safe mode.
|
43
|
+
#
|
44
|
+
# Operations that took a hash of attributes had to be somewhat duplicated
|
45
|
+
# here since we do not want to allow a :safe attribute to be included in
|
46
|
+
# the args. This is because safe could be a common attribute name and we
|
47
|
+
# don't want the collision between the attribute and determining whether or
|
48
|
+
# not safe mode is allowed.
|
49
|
+
class Proxy
|
50
|
+
|
51
|
+
attr_reader :target
|
52
|
+
|
53
|
+
# Create the new +Proxy+.
|
54
|
+
#
|
55
|
+
# Options:
|
56
|
+
#
|
57
|
+
# target: Either the class or the instance.
|
58
|
+
def initialize(target)
|
59
|
+
@target = target
|
60
|
+
end
|
61
|
+
|
62
|
+
# We will use method missing to proxy calls to the target.
|
63
|
+
#
|
64
|
+
# Example:
|
65
|
+
#
|
66
|
+
# <tt>person.safely.save</tt>
|
67
|
+
def method_missing(*args)
|
68
|
+
name = args[0]
|
69
|
+
attributes = args[1] || {}
|
70
|
+
@target.send(name, attributes.merge(:safe => true))
|
71
|
+
end
|
72
|
+
|
73
|
+
# Update the +Document+ attributes in the datbase.
|
74
|
+
#
|
75
|
+
# Example:
|
76
|
+
#
|
77
|
+
# <tt>document.update_attributes(:title => "Sir")</tt>
|
78
|
+
#
|
79
|
+
# Returns:
|
80
|
+
#
|
81
|
+
# +true+ if validation passed, +false+ if not.
|
82
|
+
def update_attributes(attributes = {})
|
83
|
+
@target.write_attributes(attributes)
|
84
|
+
@target.update(:safe => true)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Update the +Document+ attributes in the datbase.
|
88
|
+
#
|
89
|
+
# Example:
|
90
|
+
#
|
91
|
+
# <tt>document.update_attributes(:title => "Sir")</tt>
|
92
|
+
#
|
93
|
+
# Returns:
|
94
|
+
#
|
95
|
+
# +true+ if validation passed, raises an error if not
|
96
|
+
def update_attributes!(attributes = {})
|
97
|
+
@target.write_attributes(attributes)
|
98
|
+
result = update(:safe => true)
|
99
|
+
@target.class.fail_validate!(self) unless result
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create a new +Document+. This will instantiate a new document and
|
104
|
+
# insert it in a single call. Will always return the document
|
105
|
+
# whether save passed or not.
|
106
|
+
#
|
107
|
+
# Example:
|
108
|
+
#
|
109
|
+
# <tt>Person.create(:title => "Mr")</tt>
|
110
|
+
#
|
111
|
+
# Returns: the +Document+.
|
112
|
+
def create(attributes = {})
|
113
|
+
@target.new(attributes).tap { |doc| doc.insert(:safe => true) }
|
114
|
+
end
|
115
|
+
|
116
|
+
# Create a new +Document+. This will instantiate a new document and
|
117
|
+
# insert it in a single call. Will always return the document
|
118
|
+
# whether save passed or not, and if validation fails an error will be
|
119
|
+
# raise.
|
120
|
+
#
|
121
|
+
# Example:
|
122
|
+
#
|
123
|
+
# <tt>Person.create!(:title => "Mr")</tt>
|
124
|
+
#
|
125
|
+
# Returns: the +Document+.
|
126
|
+
def create!(attributes = {})
|
127
|
+
document = @target.new(attributes)
|
128
|
+
fail_validate!(document) if document.insert(:safe => true).errors.any?
|
129
|
+
document
|
130
|
+
end
|
131
|
+
|
132
|
+
# Delete all documents given the supplied conditions. If no conditions
|
133
|
+
# are passed, the entire collection will be dropped for performance
|
134
|
+
# benefits. Does not fire any callbacks.
|
135
|
+
#
|
136
|
+
# Example:
|
137
|
+
#
|
138
|
+
# <tt>Person.delete_all(:conditions => { :title => "Sir" })</tt>
|
139
|
+
# <tt>Person.delete_all</tt>
|
140
|
+
#
|
141
|
+
# Returns: true or raises an error.
|
142
|
+
def delete_all(conditions = {})
|
143
|
+
Mongoid::Persistence::RemoveAll.new(
|
144
|
+
@target,
|
145
|
+
{ :validate => false, :safe => true },
|
146
|
+
conditions[:conditions] || {}
|
147
|
+
).persist
|
148
|
+
end
|
149
|
+
|
150
|
+
# Delete all documents given the supplied conditions. If no conditions
|
151
|
+
# are passed, the entire collection will be dropped for performance
|
152
|
+
# benefits. Fires the destroy callbacks if conditions were passed.
|
153
|
+
#
|
154
|
+
# Example:
|
155
|
+
#
|
156
|
+
# <tt>Person.destroy_all(:conditions => { :title => "Sir" })</tt>
|
157
|
+
# <tt>Person.destroy_all</tt>
|
158
|
+
#
|
159
|
+
# Returns: true or raises an error.
|
160
|
+
def destroy_all(conditions = {})
|
161
|
+
documents = @target.all(conditions)
|
162
|
+
count = documents.count
|
163
|
+
documents.each { |doc| doc.destroy(:safe => true) }
|
164
|
+
count
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/lib/mongoid/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196469
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 2.0.0.beta.
|
11
|
+
- 11
|
12
|
+
version: 2.0.0.beta.11
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Durran Jordan
|
@@ -253,6 +253,7 @@ files:
|
|
253
253
|
- lib/mongoid/indexes.rb
|
254
254
|
- lib/mongoid/javascript/functions.yml
|
255
255
|
- lib/mongoid/javascript.rb
|
256
|
+
- lib/mongoid/keys.rb
|
256
257
|
- lib/mongoid/logger.rb
|
257
258
|
- lib/mongoid/matchers/all.rb
|
258
259
|
- lib/mongoid/matchers/default.rb
|
@@ -280,6 +281,7 @@ files:
|
|
280
281
|
- lib/mongoid/persistence.rb
|
281
282
|
- lib/mongoid/railtie.rb
|
282
283
|
- lib/mongoid/railties/database.rake
|
284
|
+
- lib/mongoid/safety.rb
|
283
285
|
- lib/mongoid/scope.rb
|
284
286
|
- lib/mongoid/state.rb
|
285
287
|
- lib/mongoid/timestamps.rb
|
@@ -301,7 +303,7 @@ has_rdoc: true
|
|
301
303
|
homepage: http://mongoid.org
|
302
304
|
licenses: []
|
303
305
|
|
304
|
-
post_install_message:
|
306
|
+
post_install_message: " _________________________________\n |:::::::::::::::::::::::::::::::::| \"I find your lack of faith disturbing.\"\n |:::::::::::::;;::::::::::::::::::|\n |:::::::::::'~||~~~``:::::::::::::| Mongoid 2 introduces\n |::::::::' .': o`:::::::::::| a different way of defining how\n |:::::::' oo | |o o ::::::::::| ids are stored on documents, as\n |::::::: 8 .'.' 8 o :::::::::| well as how foreign key fields\n |::::::: 8 | | 8 :::::::::| and indexes are stored.\n |::::::: _._| |_,...8 :::::::::|\n |::::::'~--. .--. `. `::::::::| If you were using String\n |:::::' =8 ~ \\ o ::::::::| representations of BSON::ObjectIDs\n |::::' 8._ 88. \\ o::::::::| as your document ids, all of your\n |:::' __. ,.ooo~~. \\ o`::::::| documents will now need to tell\n |::: . -. 88`78o/: \\ `:::::| Mongoid to use Strings like so:\n |::' /. o o \\ :: \\88`::::|\n |:; o|| 8 8 |d. `8 `:::| class User\n |:. - ^ ^ -' `-`::| include Mongoid::Document\n |::. .:::| identity :type => String\n |:::::..... ::' ``::| end\n |::::::::-'`- 88 `|\n |:::::-'. - :: | All ids will default to\n |:-~. . . : | BSON:ObjectIDs from now on, and\n | .. . ..: o:8 88o | Config#use_object_ids has been\n |. . ::: 8:P d888. . . | removed.\n |. . :88 88 888' . . |\n | o8 d88P . 88 ' d88P .. | Foreign key fields for relational\n | 88P 888 d8P ' 888 | associations no longer index by\n | 8 d88P.'d:8 .- dP~ o8 | default - you will need to pass\n | 888 888 d~ o888 LS | :index => true to the association\n |_________________________________| definition to have the field indexed\n\n or create the index manually, which is the preferred method. Note that\n if you were using String ids and now want to use object ids instead you\n will have to migrate your database manually - Mongoid cannot perform\n this for you automatically. If you were using custom composite keys,\n these will need to be defined as Strings since they cannot be converted.\n\n Please see the following gist for assistance in migrating the database\n via the Ruby driver (thanks to Kyle Banker):\n\n http://gist.github.com/489098\n\n"
|
305
307
|
rdoc_options: []
|
306
308
|
|
307
309
|
require_paths:
|