mongoid 2.0.0.beta.7 → 2.0.0.beta.8
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/lib/mongoid.rb +2 -9
- data/lib/mongoid/associations/embedded_in.rb +3 -1
- data/lib/mongoid/associations/embeds_many.rb +16 -4
- data/lib/mongoid/associations/embeds_one.rb +5 -1
- data/lib/mongoid/attributes.rb +40 -5
- data/lib/mongoid/components.rb +0 -1
- data/lib/mongoid/criteria.rb +4 -1
- data/lib/mongoid/criterion/optional.rb +38 -2
- data/lib/mongoid/document.rb +5 -8
- data/lib/mongoid/errors.rb +46 -39
- data/lib/mongoid/extensions.rb +11 -1
- data/lib/mongoid/extensions/array/conversions.rb +5 -9
- data/lib/mongoid/extensions/boolean/conversions.rb +11 -6
- data/lib/mongoid/extensions/false_class/equality.rb +13 -0
- data/lib/mongoid/extensions/hash/accessors.rb +5 -1
- data/lib/mongoid/extensions/hash/assimilation.rb +3 -2
- data/lib/mongoid/extensions/symbol/inflections.rb +3 -2
- data/lib/mongoid/extensions/true_class/equality.rb +13 -0
- data/lib/mongoid/field.rb +10 -3
- data/lib/mongoid/fields.rb +1 -0
- data/lib/mongoid/finders.rb +2 -2
- data/lib/mongoid/hierarchy.rb +1 -3
- data/lib/mongoid/paranoia.rb +106 -0
- data/lib/mongoid/persistence.rb +1 -1
- data/lib/mongoid/persistence/insert.rb +1 -0
- data/lib/mongoid/persistence/insert_embedded.rb +2 -1
- data/lib/mongoid/timestamps.rb +3 -0
- data/lib/mongoid/version.rb +1 -1
- metadata +12 -10
- data/lib/mongoid/observable.rb +0 -30
data/lib/mongoid.rb
CHANGED
@@ -19,13 +19,6 @@
|
|
19
19
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
require "rubygems"
|
23
|
-
|
24
|
-
gem "activemodel", "~>3.0.0.beta"
|
25
|
-
gem "tzinfo", "~>0.3.22"
|
26
|
-
gem "will_paginate", "~>3.0.pre"
|
27
|
-
gem "mongo", "~>1.0.1"
|
28
|
-
gem "bson", "~>1.0.1"
|
29
22
|
|
30
23
|
require "delegate"
|
31
24
|
require "singleton"
|
@@ -47,7 +40,7 @@ require "active_model/validator"
|
|
47
40
|
require "active_model/validations"
|
48
41
|
require "will_paginate/collection"
|
49
42
|
require "mongo"
|
50
|
-
require "mongoid/
|
43
|
+
require "mongoid/extensions"
|
51
44
|
require "mongoid/associations"
|
52
45
|
require "mongoid/atomicity"
|
53
46
|
require "mongoid/attributes"
|
@@ -60,7 +53,6 @@ require "mongoid/criteria"
|
|
60
53
|
require "mongoid/cursor"
|
61
54
|
require "mongoid/deprecation"
|
62
55
|
require "mongoid/dirty"
|
63
|
-
require "mongoid/extensions"
|
64
56
|
require "mongoid/extras"
|
65
57
|
require "mongoid/errors"
|
66
58
|
require "mongoid/factory"
|
@@ -82,6 +74,7 @@ require "mongoid/timestamps"
|
|
82
74
|
require "mongoid/validations"
|
83
75
|
require "mongoid/versioning"
|
84
76
|
require "mongoid/components"
|
77
|
+
require "mongoid/paranoia"
|
85
78
|
require "mongoid/document"
|
86
79
|
|
87
80
|
# add railtie
|
@@ -55,8 +55,10 @@ module Mongoid #:nodoc:
|
|
55
55
|
#
|
56
56
|
# A new +EmbeddedIn+ association proxy.
|
57
57
|
def update(target, child, options)
|
58
|
-
|
58
|
+
inverse = determine_name(target, options)
|
59
|
+
child.parentize(target, inverse)
|
59
60
|
child.notify
|
61
|
+
target.unmemoize(inverse)
|
60
62
|
instantiate(child, options)
|
61
63
|
end
|
62
64
|
|
@@ -41,11 +41,24 @@ module Mongoid #:nodoc:
|
|
41
41
|
def clear
|
42
42
|
unless @target.empty?
|
43
43
|
document = @target.first
|
44
|
-
document.
|
44
|
+
document._parent.update_child(document, true) if (document._parent)
|
45
45
|
@target.clear
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
# Returns a count of the number of documents in the association that have
|
50
|
+
# actually been persisted to the database.
|
51
|
+
#
|
52
|
+
# Use #size if you want the total number of documents.
|
53
|
+
#
|
54
|
+
# Returns:
|
55
|
+
#
|
56
|
+
# The total number of persisted embedded docs, as flagged by the
|
57
|
+
# #persisted? method.
|
58
|
+
def count
|
59
|
+
@target.select(&:persisted?).size
|
60
|
+
end
|
61
|
+
|
49
62
|
# Creates a new Document and adds it to the association collection. The
|
50
63
|
# document created will be of the same class as the others in the
|
51
64
|
# association, and the attributes will be passed into the constructor and
|
@@ -69,8 +82,7 @@ module Mongoid #:nodoc:
|
|
69
82
|
# The newly created Document.
|
70
83
|
def create!(attrs = {}, type = nil)
|
71
84
|
document = create(attrs, type)
|
72
|
-
|
73
|
-
raise Errors::Validations.new(errors) unless errors.empty?
|
85
|
+
raise Errors::Validations.new(document) unless document.errors.empty?
|
74
86
|
document
|
75
87
|
end
|
76
88
|
|
@@ -174,7 +186,7 @@ module Mongoid #:nodoc:
|
|
174
186
|
else
|
175
187
|
build(attrs)
|
176
188
|
end
|
177
|
-
end
|
189
|
+
end; self
|
178
190
|
end
|
179
191
|
|
180
192
|
# Paginate the association. Will create a new criteria, set the documents
|
@@ -43,7 +43,11 @@ module Mongoid #:nodoc:
|
|
43
43
|
#
|
44
44
|
# A new target document.
|
45
45
|
def nested_build(attributes, options = nil)
|
46
|
-
|
46
|
+
unless @target.blank? && options[:update_only]
|
47
|
+
(attributes || {}).each do |key, value|
|
48
|
+
@target.write_attribute(key, value)
|
49
|
+
end
|
50
|
+
end; @target
|
47
51
|
end
|
48
52
|
|
49
53
|
class << self
|
data/lib/mongoid/attributes.rb
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
module Mongoid #:nodoc:
|
3
3
|
module Attributes
|
4
4
|
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
class_inheritable_accessor :_protected_fields
|
7
|
+
self._protected_fields = []
|
8
|
+
end
|
5
9
|
|
6
10
|
# Get the id associated with this object. This will pull the _id value out
|
7
11
|
# of the attributes +Hash+.
|
@@ -38,7 +42,15 @@ module Mongoid #:nodoc:
|
|
38
42
|
if set_allowed?(key)
|
39
43
|
write_attribute(key, value)
|
40
44
|
elsif write_allowed?(key)
|
41
|
-
|
45
|
+
if associations.include?(key.to_s) and associations[key.to_s].embedded? and value.is_a?(Hash)
|
46
|
+
if association = send(key)
|
47
|
+
association.nested_build(value)
|
48
|
+
else
|
49
|
+
send("build_#{key}", value)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
send("#{key}=", value)
|
53
|
+
end
|
42
54
|
end
|
43
55
|
end
|
44
56
|
setup_modifications
|
@@ -76,6 +88,16 @@ module Mongoid #:nodoc:
|
|
76
88
|
modify(access, @attributes.delete(name.to_s), nil)
|
77
89
|
end
|
78
90
|
|
91
|
+
# Returns true when attribute is present.
|
92
|
+
#
|
93
|
+
# Options:
|
94
|
+
#
|
95
|
+
# name: The name of the attribute to request presence on.
|
96
|
+
def attribute_present?(name)
|
97
|
+
value = read_attribute(name)
|
98
|
+
!value.blank?
|
99
|
+
end
|
100
|
+
|
79
101
|
# Returns the object type. This corresponds to the name of the class that
|
80
102
|
# this +Document+ is, which is used in determining the class to
|
81
103
|
# instantiate in various cases.
|
@@ -161,15 +183,15 @@ module Mongoid #:nodoc:
|
|
161
183
|
|
162
184
|
# Used when supplying a :limit as an option to accepts_nested_attributes_for
|
163
185
|
def limit(attributes, name, options)
|
164
|
-
|
186
|
+
if options[:limit] && attributes.size > options[:limit]
|
187
|
+
raise Mongoid::Errors::TooManyNestedAttributeRecords.new(name, options[:limit])
|
188
|
+
end
|
165
189
|
end
|
166
190
|
|
167
191
|
# Return true if writing to the given field is allowed
|
168
192
|
def write_allowed?(key)
|
169
193
|
name = key.to_s
|
170
|
-
|
171
|
-
return true unless existing
|
172
|
-
existing.accessible?
|
194
|
+
!self._protected_fields.include?(name)
|
173
195
|
end
|
174
196
|
|
175
197
|
module ClassMethods
|
@@ -202,6 +224,19 @@ module Mongoid #:nodoc:
|
|
202
224
|
end
|
203
225
|
end
|
204
226
|
end
|
227
|
+
|
228
|
+
# Defines fields that cannot be set via mass assignment.
|
229
|
+
#
|
230
|
+
# Example:
|
231
|
+
#
|
232
|
+
# class Person
|
233
|
+
# include Mongoid::Document
|
234
|
+
# field :security_code
|
235
|
+
# attr_protected :security_code
|
236
|
+
# end
|
237
|
+
def attr_protected(*names)
|
238
|
+
_protected_fields.concat(names.flatten.map(&:to_s))
|
239
|
+
end
|
205
240
|
end
|
206
241
|
end
|
207
242
|
end
|
data/lib/mongoid/components.rb
CHANGED
data/lib/mongoid/criteria.rb
CHANGED
@@ -160,7 +160,10 @@ module Mongoid #:nodoc:
|
|
160
160
|
# Returns the selector and options as a +Hash+ that would be passed to a
|
161
161
|
# scope for use with named scopes.
|
162
162
|
def scoped
|
163
|
-
|
163
|
+
scope_options = @options.dup
|
164
|
+
sorting = scope_options.delete(:sort)
|
165
|
+
scope_options[:order_by] = sorting if sorting
|
166
|
+
{ :where => @selector }.merge(scope_options)
|
164
167
|
end
|
165
168
|
|
166
169
|
# Translate the supplied arguments into a +Criteria+ object.
|
@@ -2,6 +2,21 @@
|
|
2
2
|
module Mongoid #:nodoc:
|
3
3
|
module Criterion #:nodoc:
|
4
4
|
module Optional
|
5
|
+
|
6
|
+
# Adds fields to be sorted in ascending order. Will add them in the order
|
7
|
+
# they were passed into the method.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# <tt>criteria.ascending(:title, :dob)</tt>
|
12
|
+
def ascending(*fields)
|
13
|
+
@options[:sort] = [] unless @options[:sort] || fields.first.nil?
|
14
|
+
fields.flatten.each { |field| @options[:sort] << [ field, :asc ] }
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
alias :asc :ascending
|
19
|
+
|
5
20
|
# Tells the criteria that the cursor that gets returned needs to be
|
6
21
|
# cached. This is so multiple iterations don't hit the database multiple
|
7
22
|
# times, however this is not advisable when working with large data sets
|
@@ -23,6 +38,20 @@ module Mongoid #:nodoc:
|
|
23
38
|
@options[:cache] == true
|
24
39
|
end
|
25
40
|
|
41
|
+
# Adds fields to be sorted in descending order. Will add them in the order
|
42
|
+
# they were passed into the method.
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
#
|
46
|
+
# <tt>criteria.descending(:title, :dob)</tt>
|
47
|
+
def descending(*fields)
|
48
|
+
@options[:sort] = [] unless @options[:sort] || fields.first.nil?
|
49
|
+
fields.flatten.each { |field| @options[:sort] << [ field, :desc ] }
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
alias :desc :descending
|
54
|
+
|
26
55
|
# Flags the criteria to execute against a read-only slave in the pool
|
27
56
|
# instead of master.
|
28
57
|
#
|
@@ -110,8 +139,15 @@ module Mongoid #:nodoc:
|
|
110
139
|
# <tt>criteria.order_by([[:field1, :asc], [:field2, :desc]])</tt>
|
111
140
|
#
|
112
141
|
# Returns: <tt>self</tt>
|
113
|
-
def order_by(
|
114
|
-
@options[:sort] =
|
142
|
+
def order_by(*args)
|
143
|
+
@options[:sort] = [] unless @options[:sort] || args.first.nil?
|
144
|
+
arguments = args.first
|
145
|
+
case arguments
|
146
|
+
when Hash then arguments.each { |field, direction| @options[:sort] << [ field, direction ] }
|
147
|
+
when Array then @options[:sort].concat(arguments)
|
148
|
+
when Complex
|
149
|
+
args.flatten.each { |complex| @options[:sort] << [ complex.key, complex.operator.to_sym ] }
|
150
|
+
end; self
|
115
151
|
end
|
116
152
|
|
117
153
|
# Adds a criterion to the +Criteria+ that specifies how many results to skip
|
data/lib/mongoid/document.rb
CHANGED
@@ -141,13 +141,13 @@ module Mongoid #:nodoc:
|
|
141
141
|
"#<#{self.class.name} _id: #{id}, #{attrs * ', '}>"
|
142
142
|
end
|
143
143
|
|
144
|
-
# Notify
|
144
|
+
# Notify parent of an update.
|
145
145
|
#
|
146
146
|
# Example:
|
147
147
|
#
|
148
148
|
# <tt>person.notify</tt>
|
149
149
|
def notify
|
150
|
-
|
150
|
+
_parent.update_child(self) if _parent
|
151
151
|
end
|
152
152
|
|
153
153
|
# Return the attributes hash.
|
@@ -178,7 +178,7 @@ module Mongoid #:nodoc:
|
|
178
178
|
[ self ]
|
179
179
|
end
|
180
180
|
|
181
|
-
#
|
181
|
+
# Recieve a notify call from a child +Document+. This will either update
|
182
182
|
# existing attributes on the +Document+ or clear them out for the child if
|
183
183
|
# the clear boolean is provided.
|
184
184
|
#
|
@@ -186,18 +186,15 @@ module Mongoid #:nodoc:
|
|
186
186
|
#
|
187
187
|
# child: The child +Document+ that sent the notification.
|
188
188
|
# clear: Will clear out the child's attributes if set to true.
|
189
|
-
|
190
|
-
# This will also cause the observing +Document+ to notify it's parent if
|
191
|
-
# there is any.
|
192
|
-
def observe(child, clear = false)
|
189
|
+
def update_child(child, clear = false)
|
193
190
|
name = child.association_name
|
194
191
|
attrs = child.instance_variable_get(:@attributes)
|
195
192
|
if clear
|
196
193
|
@attributes.delete(name)
|
197
194
|
else
|
195
|
+
# check good for array only
|
198
196
|
@attributes.insert(name, attrs) unless @attributes[name] && @attributes[name].include?(attrs)
|
199
197
|
end
|
200
|
-
notify
|
201
198
|
end
|
202
199
|
end
|
203
200
|
end
|
data/lib/mongoid/errors.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
module Mongoid #:nodoc
|
3
3
|
module Errors #:nodoc
|
4
4
|
|
5
|
+
# Default parent Mongoid error for all custom errors
|
6
|
+
class MongoidError < StandardError; end
|
7
|
+
|
5
8
|
# Raised when querying the database for a document by a specific id which
|
6
9
|
# does not exist. If multiple ids were passed then it will display all of
|
7
10
|
# those.
|
@@ -9,12 +12,12 @@ module Mongoid #:nodoc
|
|
9
12
|
# Example:
|
10
13
|
#
|
11
14
|
# <tt>DocumentNotFound.new(Person, ["1", "2"])</tt>
|
12
|
-
class DocumentNotFound <
|
15
|
+
class DocumentNotFound < MongoidError
|
16
|
+
attr_reader :klass, :indentifiers
|
13
17
|
def initialize(klass, ids)
|
14
|
-
@klass
|
15
|
-
|
16
|
-
|
17
|
-
"Document not found for class #{@klass} and id(s) #{@identifier}"
|
18
|
+
@klass = klass
|
19
|
+
@identifiers = ids.is_a?(Array) ? ids.join(", ") : ids
|
20
|
+
super("Document not found for class #{@klass} with id(s) #{@identifiers}")
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
@@ -23,7 +26,7 @@ module Mongoid #:nodoc
|
|
23
26
|
# Example:
|
24
27
|
#
|
25
28
|
# <tt>InvalidOptions.new</tt>
|
26
|
-
class InvalidOptions <
|
29
|
+
class InvalidOptions < MongoidError; end
|
27
30
|
|
28
31
|
# Raised when the database connection has not been set up properly, either
|
29
32
|
# by attempting to set an object on the db that is not a +Mongo::DB+, or
|
@@ -32,12 +35,24 @@ module Mongoid #:nodoc
|
|
32
35
|
# Example:
|
33
36
|
#
|
34
37
|
# <tt>InvalidDatabase.new("Not a DB")</tt>
|
35
|
-
class InvalidDatabase <
|
38
|
+
class InvalidDatabase < MongoidError
|
39
|
+
attr_reader :database
|
36
40
|
def initialize(database)
|
37
41
|
@database = database
|
42
|
+
super("Database should be a Mongo::DB, not #{@database.class.name}")
|
38
43
|
end
|
39
|
-
|
40
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
# Raised when trying to get or set a value for a defined field, where the
|
47
|
+
# type of the object does not match the defined field type.
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
#
|
51
|
+
# <tt>InvalidType.new(Array, "Not an Array")</tt>
|
52
|
+
class InvalidType < MongoidError
|
53
|
+
def initialize(klass, value)
|
54
|
+
super("Field was defined as a(n) #{klass.name}, but received a #{value.class.name} " +
|
55
|
+
"with the value #{value.inspect}.")
|
41
56
|
end
|
42
57
|
end
|
43
58
|
|
@@ -46,12 +61,9 @@ module Mongoid #:nodoc
|
|
46
61
|
# Example:
|
47
62
|
#
|
48
63
|
# <tt>UnsupportedVersion.new(Mongo::ServerVersion.new("1.3.1"))</tt>
|
49
|
-
class UnsupportedVersion <
|
64
|
+
class UnsupportedVersion < MongoidError
|
50
65
|
def initialize(version)
|
51
|
-
|
52
|
-
end
|
53
|
-
def message
|
54
|
-
"MongoDB #{@version} not supported, please upgrade to #{Mongoid::MONGODB_VERSION}"
|
66
|
+
super("MongoDB #{version} not supported, please upgrade to #{Mongoid::MONGODB_VERSION}")
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
@@ -61,12 +73,11 @@ module Mongoid #:nodoc
|
|
61
73
|
# Example:
|
62
74
|
#
|
63
75
|
# <tt>Validations.new(person.errors)</tt>
|
64
|
-
class Validations <
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
"Validation Failed: " + @errors.full_messages.join(", ")
|
76
|
+
class Validations < MongoidError
|
77
|
+
attr_reader :document
|
78
|
+
def initialize(document)
|
79
|
+
@document = document
|
80
|
+
super("Validation Failed: #{@document.errors.full_messages.join(", ")}")
|
70
81
|
end
|
71
82
|
end
|
72
83
|
|
@@ -76,14 +87,13 @@ module Mongoid #:nodoc
|
|
76
87
|
# Example:
|
77
88
|
#
|
78
89
|
# <tt>InvalidCollection.new(Address)</tt>
|
79
|
-
class InvalidCollection <
|
90
|
+
class InvalidCollection < MongoidError
|
91
|
+
attr_reader :klass
|
80
92
|
def initialize(klass)
|
81
93
|
@klass = klass
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
"since it is an embedded document, please access a collection from " +
|
86
|
-
"the root document"
|
94
|
+
super("Access to the collection for #{@klass.name} is not allowed " +
|
95
|
+
"since it is an embedded document, please access a collection from " +
|
96
|
+
"the root document")
|
87
97
|
end
|
88
98
|
end
|
89
99
|
|
@@ -93,15 +103,14 @@ module Mongoid #:nodoc
|
|
93
103
|
# Example:
|
94
104
|
#
|
95
105
|
# <tt>InvalidField.new('collection')</tt>
|
96
|
-
class InvalidField <
|
106
|
+
class InvalidField < MongoidError
|
107
|
+
attr_reader :name
|
97
108
|
def initialize(name)
|
98
109
|
@name = name
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
"or method names. Use Document#instance_methods to see what " +
|
104
|
-
"names this includes."
|
110
|
+
super("Defining a field named '#{@name}' is not allowed. " +
|
111
|
+
"Do not define fields that conflict with Mongoid internal attributes " +
|
112
|
+
"or method names. Use Document#instance_methods to see what " +
|
113
|
+
"names this includes.")
|
105
114
|
end
|
106
115
|
end
|
107
116
|
|
@@ -111,13 +120,11 @@ module Mongoid #:nodoc
|
|
111
120
|
# Example:
|
112
121
|
#
|
113
122
|
#<tt>TooManyNestedAttributeRecords.new('association', limit)
|
114
|
-
class TooManyNestedAttributeRecords <
|
123
|
+
class TooManyNestedAttributeRecords < MongoidError
|
124
|
+
attr_reader :association, :limit
|
115
125
|
def initialize(association, limit)
|
116
|
-
@association = association.to_s.humanize.capitalize
|
117
|
-
@
|
118
|
-
end
|
119
|
-
def message
|
120
|
-
"Accept Nested Attributes for #{@association} is limited to #{@limit} records"
|
126
|
+
@association, @limit = association.to_s.humanize.capitalize, limit
|
127
|
+
super("Accept Nested Attributes for #{@association} is limited to #{@limit} records")
|
121
128
|
end
|
122
129
|
end
|
123
130
|
end
|
data/lib/mongoid/extensions.rb
CHANGED
@@ -11,6 +11,7 @@ require "mongoid/extensions/binary/conversions"
|
|
11
11
|
require "mongoid/extensions/boolean/conversions"
|
12
12
|
require "mongoid/extensions/date/conversions"
|
13
13
|
require "mongoid/extensions/datetime/conversions"
|
14
|
+
require "mongoid/extensions/false_class/equality"
|
14
15
|
require "mongoid/extensions/float/conversions"
|
15
16
|
require "mongoid/extensions/hash/accessors"
|
16
17
|
require "mongoid/extensions/hash/assimilation"
|
@@ -24,6 +25,7 @@ require "mongoid/extensions/proc/scoping"
|
|
24
25
|
require "mongoid/extensions/string/conversions"
|
25
26
|
require "mongoid/extensions/string/inflections"
|
26
27
|
require "mongoid/extensions/symbol/inflections"
|
28
|
+
require "mongoid/extensions/true_class/equality"
|
27
29
|
require "mongoid/extensions/objectid/conversions"
|
28
30
|
|
29
31
|
class Array #:nodoc
|
@@ -46,7 +48,7 @@ class Binary #:nodoc
|
|
46
48
|
end
|
47
49
|
|
48
50
|
class Boolean #:nodoc
|
49
|
-
|
51
|
+
include Mongoid::Extensions::Boolean::Conversions
|
50
52
|
end
|
51
53
|
|
52
54
|
class DateTime #:nodoc
|
@@ -59,6 +61,10 @@ class Date #:nodoc
|
|
59
61
|
extend Mongoid::Extensions::Date::Conversions
|
60
62
|
end
|
61
63
|
|
64
|
+
class FalseClass #:nodoc
|
65
|
+
include Mongoid::Extensions::FalseClass::Equality
|
66
|
+
end
|
67
|
+
|
62
68
|
class Float #:nodoc
|
63
69
|
extend Mongoid::Extensions::Float::Conversions
|
64
70
|
end
|
@@ -101,6 +107,10 @@ class Time #:nodoc
|
|
101
107
|
extend Mongoid::Extensions::TimeConversions
|
102
108
|
end
|
103
109
|
|
110
|
+
class TrueClass #:nodoc
|
111
|
+
include Mongoid::Extensions::TrueClass::Equality
|
112
|
+
end
|
113
|
+
|
104
114
|
class BSON::ObjectID #:nodoc
|
105
115
|
extend Mongoid::Extensions::ObjectID::Conversions
|
106
116
|
end
|
@@ -6,18 +6,14 @@ module Mongoid #:nodoc:
|
|
6
6
|
module Conversions #:nodoc:
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
-
# Converts this array into an array of hashes.
|
10
|
-
def mongoidize
|
11
|
-
collect { |obj| obj.attributes }
|
12
|
-
end
|
13
|
-
|
14
9
|
module ClassMethods #:nodoc:
|
15
|
-
def
|
16
|
-
value
|
17
|
-
end
|
18
|
-
def set(value)
|
10
|
+
def raise_or_return(value)
|
11
|
+
raise Mongoid::Errors::InvalidType.new(::Array, value) unless value.is_a?(::Array)
|
19
12
|
value
|
20
13
|
end
|
14
|
+
|
15
|
+
alias :get :raise_or_return
|
16
|
+
alias :set :raise_or_return
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
@@ -3,18 +3,23 @@ module Mongoid #:nodoc:
|
|
3
3
|
module Extensions #:nodoc:
|
4
4
|
module Boolean #:nodoc:
|
5
5
|
module Conversions #:nodoc:
|
6
|
+
extend ActiveSupport::Concern
|
6
7
|
|
7
8
|
BOOLEAN_MAP = {
|
8
9
|
true => true, "true" => true, "TRUE" => true, "1" => true, 1 => true, 1.0 => true,
|
9
10
|
false => false, "false" => false, "FALSE" => false, "0" => false, 0 => false, 0.0 => false
|
10
11
|
}
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
module ClassMethods #:nodoc
|
14
|
+
|
15
|
+
def set(value)
|
16
|
+
value = BOOLEAN_MAP[value]
|
17
|
+
value.nil? ? nil : value
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(value)
|
21
|
+
value
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -21,7 +21,11 @@ module Mongoid #:nodoc:
|
|
21
21
|
def insert(key, attrs)
|
22
22
|
elements = self[key]
|
23
23
|
if elements
|
24
|
-
elements.
|
24
|
+
if elements.kind_of?(::Array)
|
25
|
+
elements.merge!(attrs)
|
26
|
+
else
|
27
|
+
self[key] = attrs.reverse_merge!(elements)
|
28
|
+
end
|
25
29
|
else
|
26
30
|
self[key] = key.singular? ? attrs : [attrs]
|
27
31
|
end
|
@@ -27,11 +27,12 @@ module Mongoid #:nodoc:
|
|
27
27
|
protected
|
28
28
|
|
29
29
|
def init(parent, child, options)
|
30
|
-
child.
|
30
|
+
child.parentize(parent, options.name)
|
31
31
|
child.write_attributes(self)
|
32
32
|
child.identify
|
33
33
|
child.reset_modifications
|
34
|
-
child.
|
34
|
+
child.notify
|
35
|
+
child
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -23,8 +23,9 @@ module Mongoid #:nodoc:
|
|
23
23
|
to_s.plural?
|
24
24
|
end
|
25
25
|
|
26
|
-
[ "
|
27
|
-
"
|
26
|
+
[ "asc", "ascending", "desc", "descending", "gt", "lt", "gte",
|
27
|
+
"lte", "ne", "near", "in", "nin", "mod", "all", "size", "exists",
|
28
|
+
"within", ["matches","elemMatch"] ].each do |oper|
|
28
29
|
m, oper = oper
|
29
30
|
oper = m unless oper
|
30
31
|
class_eval <<-OPERATORS
|
data/lib/mongoid/field.rb
CHANGED
@@ -43,12 +43,12 @@ module Mongoid #:nodoc:
|
|
43
43
|
# <tt>Field.new(:score, :default => 0)</tt>
|
44
44
|
def initialize(name, options = {})
|
45
45
|
check_name!(name)
|
46
|
+
@type = options[:type] || String
|
46
47
|
@name, @default = name, options[:default]
|
47
48
|
@copyable = (@default.is_a?(Array) || @default.is_a?(Hash))
|
48
|
-
@type = options[:type] || String
|
49
49
|
@accessible = options.has_key?(:accessible) ? options[:accessible] : true
|
50
|
-
|
51
50
|
@options = options
|
51
|
+
check_default!
|
52
52
|
end
|
53
53
|
|
54
54
|
# Used for setting an object in the attributes hash. If nil is provided the
|
@@ -70,7 +70,14 @@ module Mongoid #:nodoc:
|
|
70
70
|
|
71
71
|
# Check if the name is valid.
|
72
72
|
def check_name!(name)
|
73
|
-
raise Errors::InvalidField.new(name) if Mongoid.destructive_fields.include?(name.to_s)
|
73
|
+
raise Mongoid::Errors::InvalidField.new(name) if Mongoid.destructive_fields.include?(name.to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
def check_default!
|
77
|
+
return if @default.is_a?(Proc)
|
78
|
+
if !@default.nil? && !@default.is_a?(@type)
|
79
|
+
raise Mongoid::Errors::InvalidType.new(@type, @default)
|
80
|
+
end
|
74
81
|
end
|
75
82
|
end
|
76
83
|
end
|
data/lib/mongoid/fields.rb
CHANGED
data/lib/mongoid/finders.rb
CHANGED
@@ -25,7 +25,7 @@ module Mongoid #:nodoc:
|
|
25
25
|
# Returns a count of matching records in the database based on the
|
26
26
|
# provided arguments.
|
27
27
|
#
|
28
|
-
# <tt>Person.count(:
|
28
|
+
# <tt>Person.count(:conditions => { :attribute => "value" })</tt>
|
29
29
|
def count(*args)
|
30
30
|
Criteria.translate(self, *args).count
|
31
31
|
end
|
@@ -33,7 +33,7 @@ module Mongoid #:nodoc:
|
|
33
33
|
# Returns true if there are on document in database based on the
|
34
34
|
# provided arguments.
|
35
35
|
#
|
36
|
-
# <tt>Person.exists?(:
|
36
|
+
# <tt>Person.exists?(:conditions => { :attribute => "value" })</tt>
|
37
37
|
def exists?(*args)
|
38
38
|
Criteria.translate(self, *args).limit(1).count == 1
|
39
39
|
end
|
data/lib/mongoid/hierarchy.rb
CHANGED
@@ -47,8 +47,7 @@ module Mongoid #:nodoc
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Sets up a child/parent association. This is used for newly created
|
50
|
-
# objects so they can be properly added to the graph
|
51
|
-
# observers set up properly.
|
50
|
+
# objects so they can be properly added to the graph.
|
52
51
|
#
|
53
52
|
# Options:
|
54
53
|
#
|
@@ -61,7 +60,6 @@ module Mongoid #:nodoc
|
|
61
60
|
def parentize(object, association_name)
|
62
61
|
self._parent = object
|
63
62
|
self.association_name = association_name.to_s
|
64
|
-
add_observer(object)
|
65
63
|
end
|
66
64
|
|
67
65
|
# Return the root +Document+ in the object graph. If the current +Document+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Paranoid #:nodoc:
|
4
|
+
# Find deleted documents
|
5
|
+
#
|
6
|
+
# Examples:
|
7
|
+
#
|
8
|
+
# <tt>Person.deleted</tt> # all deleted employees
|
9
|
+
# <tt>Company.first.employees.deleted</tt> # works with a join
|
10
|
+
# <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt> # retrieve by id a deleted person
|
11
|
+
def deleted
|
12
|
+
where(:deleted_at.exists => false)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Include this module to get soft deletion of root level documents.
|
17
|
+
# This will add a deleted_at field to the +Document+, managed automatically.
|
18
|
+
# Potentially incompatible with unique indices. (if collisions with deleted items)
|
19
|
+
#
|
20
|
+
# To use:
|
21
|
+
#
|
22
|
+
# class Person
|
23
|
+
# include Mongoid::Document
|
24
|
+
# include Mongoid::Paranoia
|
25
|
+
# end
|
26
|
+
module Paranoia
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
included do
|
30
|
+
Mongoid::Criteria.send(:include, Mongoid::Paranoid)
|
31
|
+
field :deleted_at, :type => Time
|
32
|
+
end
|
33
|
+
|
34
|
+
# Delete the paranoid +Document+ from the database completely. This will
|
35
|
+
# run the destroy callbacks.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
#
|
39
|
+
# <tt>document.destroy!</tt>
|
40
|
+
def destroy!
|
41
|
+
run_callbacks(:destroy) { delete! }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Delete the paranoid +Document+ from the database completely.
|
45
|
+
#
|
46
|
+
# Example:
|
47
|
+
#
|
48
|
+
# <tt>document.delete!</tt>
|
49
|
+
def delete!
|
50
|
+
@destroyed = true
|
51
|
+
Mongoid::Persistence::Remove.new(self).persist
|
52
|
+
end
|
53
|
+
|
54
|
+
# Delete the +Document+, will set the deleted_at timestamp and not actually
|
55
|
+
# delete it.
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
#
|
59
|
+
# <tt>document._remove</tt>
|
60
|
+
#
|
61
|
+
# Returns:
|
62
|
+
#
|
63
|
+
# true
|
64
|
+
def _remove
|
65
|
+
now = Time.now
|
66
|
+
collection.update({ :_id => self.id }, { '$set' => { :deleted_at => Time.now } })
|
67
|
+
@attributes["deleted_at"] = now
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
alias :delete :_remove
|
72
|
+
|
73
|
+
# Determines if this document is destroyed.
|
74
|
+
#
|
75
|
+
# Returns:
|
76
|
+
#
|
77
|
+
# true if the +Document+ was destroyed.
|
78
|
+
def destroyed?
|
79
|
+
@destroyed || !!deleted_at
|
80
|
+
end
|
81
|
+
|
82
|
+
# Restores a previously soft-deleted document. Handles this by removing the
|
83
|
+
# deleted_at flag.
|
84
|
+
#
|
85
|
+
# Example:
|
86
|
+
#
|
87
|
+
# <tt>document.restore</tt>
|
88
|
+
def restore
|
89
|
+
collection.update({ :_id => self.id }, { '$unset' => { :deleted_at => true } })
|
90
|
+
@attributes.delete("deleted_at")
|
91
|
+
end
|
92
|
+
|
93
|
+
module ClassMethods #:nodoc:
|
94
|
+
|
95
|
+
# Override the default +Criteria+ accessor to only get existing
|
96
|
+
# documents.
|
97
|
+
#
|
98
|
+
# Returns:
|
99
|
+
#
|
100
|
+
# A +Criteria+ for deleted_at not existing.
|
101
|
+
def criteria
|
102
|
+
super.where(:deleted_at.exists => false)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -33,10 +33,11 @@ module Mongoid #:nodoc:
|
|
33
33
|
else
|
34
34
|
update = { @document._inserter => { @document._position => @document.raw_attributes } }
|
35
35
|
@collection.update(parent._selector, update, @options.merge(:multi => false))
|
36
|
+
@document.new_record = false
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
39
|
-
@document
|
40
|
+
@document
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
data/lib/mongoid/timestamps.rb
CHANGED
@@ -7,6 +7,9 @@ module Mongoid #:nodoc:
|
|
7
7
|
field :updated_at, :type => Time
|
8
8
|
set_callback :create, :before, :set_created_at
|
9
9
|
set_callback :save, :before, :set_updated_at
|
10
|
+
|
11
|
+
class_inheritable_accessor :record_timestamps, :instance_writer => false
|
12
|
+
self.record_timestamps = true
|
10
13
|
end
|
11
14
|
|
12
15
|
# Update the created_at field on the Document to the current time. This is
|
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: 62196467
|
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
|
+
- 8
|
12
|
+
version: 2.0.0.beta.8
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Durran Jordan
|
@@ -77,12 +77,12 @@ dependencies:
|
|
77
77
|
requirements:
|
78
78
|
- - ~>
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
hash:
|
80
|
+
hash: 17
|
81
81
|
segments:
|
82
82
|
- 1
|
83
83
|
- 0
|
84
|
-
-
|
85
|
-
version: 1.0.
|
84
|
+
- 3
|
85
|
+
version: 1.0.3
|
86
86
|
type: :runtime
|
87
87
|
version_requirements: *id004
|
88
88
|
- !ruby/object:Gem::Dependency
|
@@ -93,12 +93,12 @@ dependencies:
|
|
93
93
|
requirements:
|
94
94
|
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
hash:
|
96
|
+
hash: 17
|
97
97
|
segments:
|
98
98
|
- 1
|
99
99
|
- 0
|
100
|
-
-
|
101
|
-
version: 1.0.
|
100
|
+
- 3
|
101
|
+
version: 1.0.3
|
102
102
|
type: :runtime
|
103
103
|
version_requirements: *id005
|
104
104
|
- !ruby/object:Gem::Dependency
|
@@ -193,6 +193,7 @@ files:
|
|
193
193
|
- lib/mongoid/extensions/boolean/conversions.rb
|
194
194
|
- lib/mongoid/extensions/date/conversions.rb
|
195
195
|
- lib/mongoid/extensions/datetime/conversions.rb
|
196
|
+
- lib/mongoid/extensions/false_class/equality.rb
|
196
197
|
- lib/mongoid/extensions/float/conversions.rb
|
197
198
|
- lib/mongoid/extensions/hash/accessors.rb
|
198
199
|
- lib/mongoid/extensions/hash/assimilation.rb
|
@@ -209,6 +210,7 @@ files:
|
|
209
210
|
- lib/mongoid/extensions/string/inflections.rb
|
210
211
|
- lib/mongoid/extensions/symbol/inflections.rb
|
211
212
|
- lib/mongoid/extensions/time_conversions.rb
|
213
|
+
- lib/mongoid/extensions/true_class/equality.rb
|
212
214
|
- lib/mongoid/extensions.rb
|
213
215
|
- lib/mongoid/extras.rb
|
214
216
|
- lib/mongoid/factory.rb
|
@@ -234,7 +236,7 @@ files:
|
|
234
236
|
- lib/mongoid/matchers.rb
|
235
237
|
- lib/mongoid/memoization.rb
|
236
238
|
- lib/mongoid/named_scope.rb
|
237
|
-
- lib/mongoid/
|
239
|
+
- lib/mongoid/paranoia.rb
|
238
240
|
- lib/mongoid/paths.rb
|
239
241
|
- lib/mongoid/persistence/command.rb
|
240
242
|
- lib/mongoid/persistence/insert.rb
|
data/lib/mongoid/observable.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Mongoid #:nodoc:
|
3
|
-
module Observable #:nodoc:
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
included do
|
6
|
-
attr_reader :observers
|
7
|
-
end
|
8
|
-
|
9
|
-
# Add an observer to this object. This mimics the standard Ruby observable
|
10
|
-
# library.
|
11
|
-
#
|
12
|
-
# Example:
|
13
|
-
#
|
14
|
-
# <tt>address.add_observer(person)</tt>
|
15
|
-
def add_observer(object)
|
16
|
-
@observers ||= []
|
17
|
-
@observers.push(object)
|
18
|
-
end
|
19
|
-
|
20
|
-
# Notify all the objects observing this object of an update. All observers
|
21
|
-
# need to respond to the update method in order to handle this.
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
#
|
25
|
-
# <tt>document.notify_observers(self)</tt>
|
26
|
-
def notify_observers(*args)
|
27
|
-
@observers.dup.each { |observer| observer.observe(*args) } if @observers
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|