mongoid 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -1
- data/Rakefile +3 -2
- data/lib/config/locales/bg.yml +6 -0
- data/lib/config/locales/de.yml +6 -0
- data/lib/config/locales/en-GB.yml +48 -0
- data/lib/config/locales/en.yml +6 -3
- data/lib/config/locales/es.yml +6 -0
- data/lib/config/locales/fr.yml +6 -0
- data/lib/config/locales/hi.yml +39 -0
- data/lib/config/locales/hu.yml +13 -7
- data/lib/config/locales/id.yml +3 -0
- data/lib/config/locales/it.yml +7 -1
- data/lib/config/locales/ja.yml +4 -1
- data/lib/config/locales/kr.yml +9 -34
- data/lib/config/locales/nl.yml +6 -0
- data/lib/config/locales/pl.yml +6 -0
- data/lib/config/locales/pt-BR.yml +6 -0
- data/lib/config/locales/pt.yml +6 -0
- data/lib/config/locales/ro.yml +6 -0
- data/lib/config/locales/ru.yml +6 -0
- data/lib/config/locales/sv.yml +6 -0
- data/lib/config/locales/vi.yml +3 -0
- data/lib/config/locales/zh-CN.yml +6 -0
- data/lib/mongoid.rb +51 -45
- data/lib/mongoid/atomic.rb +145 -0
- data/lib/mongoid/atomic/modifiers.rb +109 -0
- data/lib/mongoid/atomic/paths.rb +3 -0
- data/lib/mongoid/atomic/paths/embedded.rb +43 -0
- data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
- data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
- data/lib/mongoid/atomic/paths/root.rb +40 -0
- data/lib/mongoid/attributes.rb +12 -23
- data/lib/mongoid/attributes/processing.rb +5 -5
- data/lib/mongoid/callbacks.rb +2 -0
- data/lib/mongoid/collection.rb +12 -59
- data/lib/mongoid/collections.rb +23 -20
- data/lib/mongoid/collections/master.rb +6 -4
- data/lib/mongoid/collections/operations.rb +1 -0
- data/lib/mongoid/collections/retry.rb +7 -0
- data/lib/mongoid/components.rb +2 -2
- data/lib/mongoid/config.rb +42 -55
- data/lib/mongoid/config/database.rb +6 -2
- data/lib/mongoid/config/replset_database.rb +7 -3
- data/lib/mongoid/contexts.rb +9 -3
- data/lib/mongoid/contexts/enumerable.rb +7 -3
- data/lib/mongoid/contexts/mongo.rb +139 -101
- data/lib/mongoid/criteria.rb +86 -69
- data/lib/mongoid/criterion/complex.rb +32 -5
- data/lib/mongoid/criterion/inclusion.rb +4 -2
- data/lib/mongoid/criterion/optional.rb +111 -86
- data/lib/mongoid/criterion/selector.rb +8 -4
- data/lib/mongoid/cursor.rb +27 -27
- data/lib/mongoid/dirty.rb +54 -214
- data/lib/mongoid/document.rb +37 -39
- data/lib/mongoid/errors/document_not_found.rb +3 -4
- data/lib/mongoid/errors/invalid_collection.rb +2 -3
- data/lib/mongoid/errors/invalid_database.rb +2 -3
- data/lib/mongoid/errors/invalid_field.rb +2 -3
- data/lib/mongoid/errors/invalid_options.rb +19 -7
- data/lib/mongoid/errors/invalid_type.rb +2 -3
- data/lib/mongoid/errors/mongoid_error.rb +5 -6
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -3
- data/lib/mongoid/errors/unsupported_version.rb +2 -3
- data/lib/mongoid/errors/validations.rb +2 -3
- data/lib/mongoid/extensions.rb +8 -62
- data/lib/mongoid/extensions/array/deletion.rb +29 -0
- data/lib/mongoid/extensions/false_class/equality.rb +14 -1
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +21 -10
- data/lib/mongoid/extensions/hash/scoping.rb +14 -1
- data/lib/mongoid/extensions/nil/collectionization.rb +12 -1
- data/lib/mongoid/extensions/object/reflections.rb +33 -2
- data/lib/mongoid/extensions/object_id/conversions.rb +2 -36
- data/lib/mongoid/extensions/proc/scoping.rb +14 -1
- data/lib/mongoid/extensions/string/conversions.rb +4 -16
- data/lib/mongoid/extensions/string/inflections.rb +35 -14
- data/lib/mongoid/extensions/symbol/inflections.rb +38 -12
- data/lib/mongoid/extensions/true_class/equality.rb +14 -1
- data/lib/mongoid/extras.rb +11 -30
- data/lib/mongoid/factory.rb +1 -1
- data/lib/mongoid/fields.rb +121 -29
- data/lib/mongoid/fields/mappings.rb +36 -0
- data/lib/mongoid/fields/serializable.rb +131 -0
- data/lib/mongoid/fields/serializable/array.rb +64 -0
- data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
- data/lib/mongoid/fields/serializable/bignum.rb +10 -0
- data/lib/mongoid/fields/serializable/binary.rb +11 -0
- data/lib/mongoid/fields/serializable/boolean.rb +44 -0
- data/lib/mongoid/fields/serializable/date.rb +51 -0
- data/lib/mongoid/fields/serializable/date_time.rb +28 -0
- data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
- data/lib/mongoid/fields/serializable/float.rb +33 -0
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +56 -0
- data/lib/mongoid/fields/serializable/foreign_keys/object.rb +43 -0
- data/lib/mongoid/fields/serializable/hash.rb +25 -0
- data/lib/mongoid/fields/serializable/integer.rb +33 -0
- data/lib/mongoid/fields/serializable/object.rb +11 -0
- data/lib/mongoid/fields/serializable/object_id.rb +32 -0
- data/lib/mongoid/fields/serializable/range.rb +42 -0
- data/lib/mongoid/fields/serializable/set.rb +42 -0
- data/lib/mongoid/fields/serializable/string.rb +28 -0
- data/lib/mongoid/fields/serializable/symbol.rb +28 -0
- data/lib/mongoid/fields/serializable/time.rb +12 -0
- data/lib/mongoid/fields/serializable/time_with_zone.rb +12 -0
- data/lib/mongoid/fields/serializable/timekeeping.rb +102 -0
- data/lib/mongoid/finders.rb +61 -37
- data/lib/mongoid/hierarchy.rb +43 -8
- data/lib/mongoid/identity_map.rb +106 -0
- data/lib/mongoid/indexes.rb +17 -1
- data/lib/mongoid/javascript.rb +2 -3
- data/lib/mongoid/keys.rb +10 -21
- data/lib/mongoid/logger.rb +22 -1
- data/lib/mongoid/matchers/all.rb +10 -0
- data/lib/mongoid/matchers/default.rb +1 -1
- data/lib/mongoid/matchers/exists.rb +10 -0
- data/lib/mongoid/matchers/gt.rb +10 -0
- data/lib/mongoid/matchers/gte.rb +10 -0
- data/lib/mongoid/matchers/in.rb +10 -0
- data/lib/mongoid/matchers/lt.rb +10 -0
- data/lib/mongoid/matchers/lte.rb +10 -0
- data/lib/mongoid/matchers/ne.rb +10 -0
- data/lib/mongoid/matchers/nin.rb +10 -0
- data/lib/mongoid/matchers/or.rb +7 -4
- data/lib/mongoid/matchers/size.rb +10 -0
- data/lib/mongoid/multi_database.rb +26 -6
- data/lib/mongoid/multi_parameter_attributes.rb +40 -17
- data/lib/mongoid/named_scope.rb +1 -2
- data/lib/mongoid/nested_attributes.rb +4 -1
- data/lib/mongoid/observer.rb +108 -5
- data/lib/mongoid/paranoia.rb +26 -26
- data/lib/mongoid/persistence.rb +15 -21
- data/lib/mongoid/persistence/atomic.rb +135 -0
- data/lib/mongoid/persistence/atomic/add_to_set.rb +11 -8
- data/lib/mongoid/persistence/atomic/bit.rb +37 -0
- data/lib/mongoid/persistence/atomic/inc.rb +9 -6
- data/lib/mongoid/persistence/atomic/operation.rb +48 -7
- data/lib/mongoid/persistence/atomic/pop.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull_all.rb +10 -9
- data/lib/mongoid/persistence/atomic/push.rb +8 -5
- data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
- data/lib/mongoid/persistence/atomic/rename.rb +31 -0
- data/lib/mongoid/persistence/atomic/set.rb +30 -0
- data/lib/mongoid/persistence/atomic/unset.rb +28 -0
- data/lib/mongoid/persistence/deletion.rb +32 -0
- data/lib/mongoid/persistence/insertion.rb +41 -0
- data/lib/mongoid/persistence/modification.rb +37 -0
- data/lib/mongoid/persistence/operations.rb +214 -0
- data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
- data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
- data/lib/mongoid/persistence/operations/insert.rb +34 -0
- data/lib/mongoid/persistence/operations/remove.rb +33 -0
- data/lib/mongoid/persistence/operations/update.rb +53 -0
- data/lib/mongoid/railtie.rb +21 -33
- data/lib/mongoid/railties/database.rake +12 -12
- data/lib/mongoid/relations.rb +9 -5
- data/lib/mongoid/relations/accessors.rb +15 -36
- data/lib/mongoid/relations/auto_save.rb +2 -2
- data/lib/mongoid/relations/binding.rb +28 -1
- data/lib/mongoid/relations/bindings/embedded/in.rb +17 -30
- data/lib/mongoid/relations/bindings/embedded/many.rb +16 -21
- data/lib/mongoid/relations/bindings/embedded/one.rb +11 -16
- data/lib/mongoid/relations/bindings/referenced/in.rb +31 -32
- data/lib/mongoid/relations/bindings/referenced/many.rb +19 -61
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -63
- data/lib/mongoid/relations/bindings/referenced/one.rb +18 -26
- data/lib/mongoid/relations/builder.rb +4 -2
- data/lib/mongoid/relations/builders.rb +21 -2
- data/lib/mongoid/relations/builders/embedded/in.rb +5 -1
- data/lib/mongoid/relations/builders/embedded/many.rb +12 -4
- data/lib/mongoid/relations/builders/embedded/one.rb +5 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +2 -2
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/in.rb +2 -5
- data/lib/mongoid/relations/builders/referenced/many.rb +2 -3
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +14 -5
- data/lib/mongoid/relations/builders/referenced/one.rb +2 -3
- data/lib/mongoid/relations/embedded/atomic.rb +2 -2
- data/lib/mongoid/relations/embedded/in.rb +72 -41
- data/lib/mongoid/relations/embedded/many.rb +116 -120
- data/lib/mongoid/relations/embedded/one.rb +59 -41
- data/lib/mongoid/relations/embedded/sort.rb +31 -0
- data/lib/mongoid/relations/macros.rb +28 -24
- data/lib/mongoid/relations/many.rb +10 -103
- data/lib/mongoid/relations/metadata.rb +335 -38
- data/lib/mongoid/relations/one.rb +7 -32
- data/lib/mongoid/relations/options.rb +47 -0
- data/lib/mongoid/relations/proxy.rb +29 -28
- data/lib/mongoid/relations/referenced/batch.rb +2 -3
- data/lib/mongoid/relations/referenced/in.rb +66 -53
- data/lib/mongoid/relations/referenced/many.rb +216 -143
- data/lib/mongoid/relations/referenced/many_to_many.rb +132 -163
- data/lib/mongoid/relations/referenced/one.rb +76 -58
- data/lib/mongoid/relations/synchronization.rb +113 -0
- data/lib/mongoid/relations/targets.rb +2 -0
- data/lib/mongoid/relations/targets/enumerable.rb +329 -0
- data/lib/mongoid/safety.rb +24 -156
- data/lib/mongoid/serialization.rb +21 -0
- data/lib/mongoid/state.rb +34 -0
- data/lib/mongoid/threaded.rb +175 -0
- data/lib/mongoid/timestamps/updated.rb +1 -1
- data/lib/mongoid/validations.rb +3 -7
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +61 -7
- data/lib/rack/mongoid.rb +2 -0
- data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +1 -1
- data/lib/rails/generators/mongoid/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +1 -1
- data/lib/rails/generators/mongoid/observer/templates/{observer.rb → observer.rb.tt} +0 -0
- data/lib/rails/mongoid.rb +17 -17
- metadata +136 -102
- data/lib/mongoid/atomicity.rb +0 -111
- data/lib/mongoid/collections/cyclic_iterator.rb +0 -34
- data/lib/mongoid/collections/slaves.rb +0 -61
- data/lib/mongoid/extensions/array/conversions.rb +0 -23
- data/lib/mongoid/extensions/array/parentization.rb +0 -13
- data/lib/mongoid/extensions/big_decimal/conversions.rb +0 -19
- data/lib/mongoid/extensions/binary/conversions.rb +0 -17
- data/lib/mongoid/extensions/boolean/conversions.rb +0 -27
- data/lib/mongoid/extensions/date/conversions.rb +0 -25
- data/lib/mongoid/extensions/datetime/conversions.rb +0 -12
- data/lib/mongoid/extensions/float/conversions.rb +0 -20
- data/lib/mongoid/extensions/hash/conversions.rb +0 -19
- data/lib/mongoid/extensions/integer/conversions.rb +0 -20
- data/lib/mongoid/extensions/object/conversions.rb +0 -25
- data/lib/mongoid/extensions/range/conversions.rb +0 -25
- data/lib/mongoid/extensions/set/conversions.rb +0 -20
- data/lib/mongoid/extensions/symbol/conversions.rb +0 -21
- data/lib/mongoid/extensions/time_conversions.rb +0 -38
- data/lib/mongoid/field.rb +0 -162
- data/lib/mongoid/paths.rb +0 -61
- data/lib/mongoid/persistence/command.rb +0 -71
- data/lib/mongoid/persistence/insert.rb +0 -53
- data/lib/mongoid/persistence/insert_embedded.rb +0 -43
- data/lib/mongoid/persistence/remove.rb +0 -44
- data/lib/mongoid/persistence/remove_all.rb +0 -40
- data/lib/mongoid/persistence/remove_embedded.rb +0 -48
- data/lib/mongoid/persistence/update.rb +0 -77
- data/lib/mongoid/safe.rb +0 -23
- data/lib/mongoid/validations/referenced.rb +0 -58
|
@@ -100,7 +100,7 @@ module Mongoid #:nodoc:
|
|
|
100
100
|
#
|
|
101
101
|
# @since 1.0.0
|
|
102
102
|
def typecast_value_for(field, value)
|
|
103
|
-
return field.
|
|
103
|
+
return field.serialize(value) if field.type === value
|
|
104
104
|
case value
|
|
105
105
|
when Hash
|
|
106
106
|
value = value.dup
|
|
@@ -112,7 +112,11 @@ module Mongoid #:nodoc:
|
|
|
112
112
|
when Regexp
|
|
113
113
|
value
|
|
114
114
|
else
|
|
115
|
-
field.type == Array
|
|
115
|
+
if field.type == Array
|
|
116
|
+
Serialization.mongoize(value, value.class)
|
|
117
|
+
else
|
|
118
|
+
field.serialize(value)
|
|
119
|
+
end
|
|
116
120
|
end
|
|
117
121
|
end
|
|
118
122
|
|
|
@@ -131,9 +135,9 @@ module Mongoid #:nodoc:
|
|
|
131
135
|
def typecast_hash_value(field, key, value)
|
|
132
136
|
case key
|
|
133
137
|
when "$exists"
|
|
134
|
-
|
|
138
|
+
Serialization.mongoize(value, Boolean)
|
|
135
139
|
when "$size"
|
|
136
|
-
|
|
140
|
+
Serialization.mongoize(value, Integer)
|
|
137
141
|
else
|
|
138
142
|
typecast_value_for(field, value)
|
|
139
143
|
end
|
data/lib/mongoid/cursor.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
module Mongoid #:nodoc
|
|
3
|
+
|
|
4
|
+
# Mongoid wrapper of the Ruby Driver cursor.
|
|
3
5
|
class Cursor
|
|
4
6
|
include Mongoid::Collections::Retry
|
|
5
7
|
include Enumerable
|
|
8
|
+
|
|
6
9
|
# Operations on the Mongo::Cursor object that will not get overriden by the
|
|
7
10
|
# Mongoid::Cursor are defined here.
|
|
8
11
|
OPERATIONS = [
|
|
@@ -24,42 +27,37 @@ module Mongoid #:nodoc
|
|
|
24
27
|
:timeout
|
|
25
28
|
]
|
|
26
29
|
|
|
27
|
-
attr_reader :collection
|
|
30
|
+
attr_reader :collection, :cursor, :klass
|
|
28
31
|
|
|
29
32
|
# The operations above will all delegate to the proxied Mongo::Cursor.
|
|
30
|
-
#
|
|
31
|
-
# Example:
|
|
32
|
-
#
|
|
33
|
-
# <tt>cursor.close</tt>
|
|
34
33
|
OPERATIONS.each do |name|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
35
|
+
def #{name}(*args)
|
|
36
|
+
retry_on_connection_failure do
|
|
37
|
+
cursor.#{name}(*args)
|
|
38
|
+
end
|
|
38
39
|
end
|
|
39
|
-
|
|
40
|
+
EOS
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
# Iterate over each document in the cursor and yield to it.
|
|
43
44
|
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
# <tt>cursor.each { |doc| p doc.title }</tt>
|
|
45
|
+
# @example Iterate over the cursor.
|
|
46
|
+
# cursor.each { |doc| p doc.title }
|
|
47
47
|
def each
|
|
48
|
-
|
|
49
|
-
yield Mongoid::Factory.from_db(
|
|
48
|
+
cursor.each do |document|
|
|
49
|
+
yield Mongoid::Factory.from_db(klass, document)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Create the new +Mongoid::Cursor+.
|
|
54
54
|
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# collection: The Mongoid::Collection instance.
|
|
58
|
-
# cursor: The Mongo::Cursor to be proxied.
|
|
59
|
-
#
|
|
60
|
-
# Example:
|
|
55
|
+
# @example Instantiate the cursor.
|
|
56
|
+
# Mongoid::Cursor.new(Person, cursor)
|
|
61
57
|
#
|
|
62
|
-
#
|
|
58
|
+
# @param [ Class ] klass The class associated with the cursor.
|
|
59
|
+
# @param [ Collection ] collection The Mongoid::Collection instance.
|
|
60
|
+
# @param [ Mongo::Cursor ] cursor The Mongo::Cursor to be proxied.
|
|
63
61
|
def initialize(klass, collection, cursor)
|
|
64
62
|
@klass, @collection, @cursor = klass, collection, cursor
|
|
65
63
|
end
|
|
@@ -67,20 +65,22 @@ module Mongoid #:nodoc
|
|
|
67
65
|
# Return the next document in the cursor. Will instantiate a new Mongoid
|
|
68
66
|
# document with the attributes.
|
|
69
67
|
#
|
|
70
|
-
#
|
|
68
|
+
# @example Get the next document.
|
|
69
|
+
# cursor.next_document
|
|
71
70
|
#
|
|
72
|
-
#
|
|
71
|
+
# @return [ Document ] The next document in the cursor.
|
|
73
72
|
def next_document
|
|
74
|
-
Mongoid::Factory.from_db(
|
|
73
|
+
Mongoid::Factory.from_db(klass, cursor.next_document)
|
|
75
74
|
end
|
|
76
75
|
|
|
77
76
|
# Returns an array of all the documents in the cursor.
|
|
78
77
|
#
|
|
79
|
-
#
|
|
78
|
+
# @example Get the cursor as an array.
|
|
79
|
+
# cursor.to_a
|
|
80
80
|
#
|
|
81
|
-
# <
|
|
81
|
+
# @return [ Array<Document> ] An array of documents.
|
|
82
82
|
def to_a
|
|
83
|
-
|
|
83
|
+
cursor.to_a.collect { |attrs| Mongoid::Factory.from_db(klass, attrs) }
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
end
|
data/lib/mongoid/dirty.rb
CHANGED
|
@@ -2,252 +2,92 @@
|
|
|
2
2
|
module Mongoid #:nodoc:
|
|
3
3
|
module Dirty #:nodoc:
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
|
+
include ActiveModel::Dirty
|
|
5
6
|
|
|
6
|
-
#
|
|
7
|
+
# Get the changed values for the document. This is a hash with the name of
|
|
8
|
+
# the field as the keys, and the values being an array of previous and
|
|
9
|
+
# current pairs.
|
|
7
10
|
#
|
|
8
|
-
#
|
|
11
|
+
# @example Get the changes.
|
|
12
|
+
# document.changes
|
|
9
13
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
# person.attribute_change("title") # [ "Sir", "Madam" ]
|
|
13
|
-
#
|
|
14
|
-
# Returns:
|
|
15
|
-
#
|
|
16
|
-
# An +Array+ containing the old and new values.
|
|
17
|
-
def attribute_change(name)
|
|
18
|
-
modifications[name]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Determines if a specific field has chaged.
|
|
22
|
-
#
|
|
23
|
-
# Example:
|
|
24
|
-
#
|
|
25
|
-
# person = Person.new(:title => "Sir")
|
|
26
|
-
# person.title = "Madam"
|
|
27
|
-
# person.attribute_changed?("title") # true
|
|
28
|
-
#
|
|
29
|
-
# Returns:
|
|
30
|
-
#
|
|
31
|
-
# +true+ if changed, +false+ if not.
|
|
32
|
-
def attribute_changed?(name)
|
|
33
|
-
modifications.include?(name)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Gets the old value for a specific field.
|
|
37
|
-
#
|
|
38
|
-
# Example:
|
|
39
|
-
#
|
|
40
|
-
# person = Person.new(:title => "Sir")
|
|
41
|
-
# person.title = "Madam"
|
|
42
|
-
# person.attribute_was("title") # "Sir"
|
|
43
|
-
#
|
|
44
|
-
# Returns:
|
|
45
|
-
#
|
|
46
|
-
# The old field value.
|
|
47
|
-
def attribute_was(name)
|
|
48
|
-
change = modifications[name]
|
|
49
|
-
change ? change[0] : attributes[name]
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Gets the names of all the fields that have changed in the document.
|
|
14
|
+
# @note This is overriding the AM::Dirty implementation to handle
|
|
15
|
+
# enumerable fields being in the hash when not actually changed.
|
|
53
16
|
#
|
|
54
|
-
#
|
|
17
|
+
# @return [ Hash ] The changed values.
|
|
55
18
|
#
|
|
56
|
-
#
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
modifications.keys
|
|
19
|
+
# @since 2.1.0
|
|
20
|
+
def changes
|
|
21
|
+
{}.tap do |hash|
|
|
22
|
+
changed.each do |name|
|
|
23
|
+
change = attribute_change(name)
|
|
24
|
+
hash[name] = change if change[0] != change[1]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
65
27
|
end
|
|
66
28
|
|
|
67
|
-
#
|
|
29
|
+
# Call this method after save, so the changes can be properly switched.
|
|
68
30
|
#
|
|
69
|
-
#
|
|
31
|
+
# This will unset the memoized children array, set new record to
|
|
32
|
+
# false, set the document as validated, and move the dirty changes.
|
|
70
33
|
#
|
|
71
|
-
#
|
|
72
|
-
# person.
|
|
73
|
-
# person.changed? # returns true
|
|
34
|
+
# @example Move the changes to previous.
|
|
35
|
+
# person.move_changes
|
|
74
36
|
#
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
37
|
+
# @since 2.1.0
|
|
38
|
+
def move_changes
|
|
39
|
+
@_children = nil
|
|
40
|
+
@previously_changed = changes
|
|
41
|
+
@validated = false
|
|
42
|
+
changed_attributes.clear
|
|
80
43
|
end
|
|
81
44
|
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
# +Array+ with the old value and new value.
|
|
45
|
+
# Remove a change from the dirty attributes hash. Used by the single field
|
|
46
|
+
# atomic updators.
|
|
85
47
|
#
|
|
86
|
-
#
|
|
48
|
+
# @example Remove a flagged change.
|
|
49
|
+
# model.remove_change(:field)
|
|
87
50
|
#
|
|
88
|
-
#
|
|
89
|
-
# person.title = "Madam"
|
|
90
|
-
# person.changes # returns { "title" => [ "Sir", "Madam" ] }
|
|
51
|
+
# @param [ Symbol, String ] name The name of the field.
|
|
91
52
|
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def changes
|
|
96
|
-
modifications
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# Call this method after save, so the changes can be properly switched.
|
|
100
|
-
#
|
|
101
|
-
# Example:
|
|
102
|
-
#
|
|
103
|
-
# <tt>person.move_changes</tt>
|
|
104
|
-
def move_changes
|
|
105
|
-
@validated = false
|
|
106
|
-
@previous_modifications = modifications.dup
|
|
107
|
-
@modifications = {}
|
|
53
|
+
# @since 2.1.0
|
|
54
|
+
def remove_change(name)
|
|
55
|
+
changed_attributes.delete(name.to_s)
|
|
108
56
|
end
|
|
109
57
|
|
|
110
58
|
# Gets all the new values for each of the changed fields, to be passed to
|
|
111
59
|
# a MongoDB $set modifier.
|
|
112
60
|
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
61
|
+
# @example Get the setters for the atomic updates.
|
|
115
62
|
# person = Person.new(:title => "Sir")
|
|
116
63
|
# person.title = "Madam"
|
|
117
64
|
# person.setters # returns { "title" => "Madam" }
|
|
118
65
|
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
# A +Hash+ of new values.
|
|
66
|
+
# @return [ Hash ] A +Hash+ of atomic setters.
|
|
122
67
|
def setters
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
68
|
+
{}.tap do |modifications|
|
|
69
|
+
changes.each_pair do |field, changes|
|
|
70
|
+
key = embedded? ? "#{atomic_position}.#{field}" : field
|
|
71
|
+
modifications[key] = changes[1]
|
|
72
|
+
end
|
|
126
73
|
end
|
|
127
74
|
end
|
|
128
75
|
|
|
129
|
-
|
|
130
|
-
# object was saved.
|
|
131
|
-
#
|
|
132
|
-
# Example:
|
|
133
|
-
#
|
|
134
|
-
# person = Person.new(:title => "Sir")
|
|
135
|
-
# person.title = "Madam"
|
|
136
|
-
# person.save!
|
|
137
|
-
# person.previous_changes # returns { "title" => [ "Sir", "Madam" ] }
|
|
138
|
-
#
|
|
139
|
-
# Returns:
|
|
140
|
-
#
|
|
141
|
-
# A +Hash+ of changes before save.
|
|
142
|
-
def previous_changes
|
|
143
|
-
@previous_modifications
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Resets a changed field back to its old value.
|
|
147
|
-
#
|
|
148
|
-
# Example:
|
|
149
|
-
#
|
|
150
|
-
# person = Person.new(:title => "Sir")
|
|
151
|
-
# person.title = "Madam"
|
|
152
|
-
# person.reset_attribute!("title")
|
|
153
|
-
# person.title # "Sir"
|
|
154
|
-
#
|
|
155
|
-
# Returns:
|
|
156
|
-
#
|
|
157
|
-
# The old field value.
|
|
158
|
-
def reset_attribute!(name)
|
|
159
|
-
value = attribute_was(name)
|
|
160
|
-
value ? attributes[name] = value : attributes.delete(name)
|
|
161
|
-
modifications.delete(name)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Sets up the modifications hash. This occurs just after the document is
|
|
165
|
-
# instantiated.
|
|
166
|
-
#
|
|
167
|
-
# Example:
|
|
168
|
-
#
|
|
169
|
-
# <tt>document.setup_notifications</tt>
|
|
170
|
-
def setup_modifications
|
|
171
|
-
@accessed ||= {}
|
|
172
|
-
@modifications ||= {}
|
|
173
|
-
@previous_modifications ||= {}
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# Reset all modifications for the document. This will wipe all the marked
|
|
177
|
-
# changes, but not reset the values.
|
|
178
|
-
#
|
|
179
|
-
# Example:
|
|
180
|
-
#
|
|
181
|
-
# <tt>document.reset_modifications</tt>
|
|
182
|
-
def reset_modifications
|
|
183
|
-
@accessed = {}
|
|
184
|
-
@modifications = {}
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
protected
|
|
188
|
-
|
|
189
|
-
# Audit the original value for a field that can be modified in place.
|
|
190
|
-
#
|
|
191
|
-
# Example:
|
|
192
|
-
#
|
|
193
|
-
# <tt>person.accessed("aliases", [ "007" ])</tt>
|
|
194
|
-
def accessed(name, value)
|
|
195
|
-
return value unless value.is_a?(Enumerable)
|
|
196
|
-
@accessed ||= {}
|
|
197
|
-
@accessed[name] = value.dup unless @accessed.has_key?(name)
|
|
198
|
-
value
|
|
199
|
-
end
|
|
76
|
+
private
|
|
200
77
|
|
|
201
|
-
# Get
|
|
78
|
+
# Get the current value for the specified attribute, if the attribute has changed.
|
|
202
79
|
#
|
|
203
|
-
#
|
|
80
|
+
# @note This is overriding the AM::Dirty implementation to read from the mongoid
|
|
81
|
+
# attributes hash, which may contain a serialized version of the attributes data. It is
|
|
82
|
+
# necessary to read the serialized version as the changed value, to allow updates to
|
|
83
|
+
# the MongoDB document to persist correctly. For example, if a DateTime field is updated
|
|
84
|
+
# it must be persisted as a UTC Time.
|
|
204
85
|
#
|
|
205
|
-
#
|
|
86
|
+
# @return [ Object ] The current value of the field, or nil if no change made.
|
|
206
87
|
#
|
|
207
|
-
#
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
def modifications
|
|
211
|
-
reset_modifications unless @modifications && @accessed
|
|
212
|
-
@accessed.each_pair do |field, value|
|
|
213
|
-
current = attributes[field]
|
|
214
|
-
@modifications[field] = [ value, current ] if current != value
|
|
215
|
-
end
|
|
216
|
-
@accessed.clear
|
|
217
|
-
@modifications
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# Audit the change of a field's value.
|
|
221
|
-
#
|
|
222
|
-
# Example:
|
|
223
|
-
#
|
|
224
|
-
# <tt>person.modify("name", "Jack", "John")</tt>
|
|
225
|
-
def modify(name, old_value, new_value)
|
|
226
|
-
attributes[name] = new_value
|
|
227
|
-
if @modifications && (old_value != new_value)
|
|
228
|
-
original = @modifications[name].first if @modifications[name]
|
|
229
|
-
@modifications[name] = [ (original || old_value), new_value ]
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
module ClassMethods #:nodoc:
|
|
234
|
-
# Add the dynamic dirty methods. These are custom methods defined on a
|
|
235
|
-
# field by field basis that wrap the dirty attribute methods.
|
|
236
|
-
#
|
|
237
|
-
# Example:
|
|
238
|
-
#
|
|
239
|
-
# person = Person.new(:title => "Sir")
|
|
240
|
-
# person.title = "Madam"
|
|
241
|
-
# person.title_change # [ "Sir", "Madam" ]
|
|
242
|
-
# person.title_changed? # true
|
|
243
|
-
# person.title_was # "Sir"
|
|
244
|
-
# person.reset_title!
|
|
245
|
-
def add_dirty_methods(name)
|
|
246
|
-
define_method("#{name}_change") { attribute_change(name) } unless instance_methods.include?("#{name}_change") || instance_methods.include?(:"#{name}_change")
|
|
247
|
-
define_method("#{name}_changed?") { attribute_changed?(name) } unless instance_methods.include?("#{name}_changed?") || instance_methods.include?(:"#{name}_changed?")
|
|
248
|
-
define_method("#{name}_was") { attribute_was(name) } unless instance_methods.include?("#{name}_was") || instance_methods.include?(:"#{name}_was")
|
|
249
|
-
define_method("reset_#{name}!") { reset_attribute!(name) } unless instance_methods.include?("reset_#{name}!") || instance_methods.include?(:"reset_#{name}!")
|
|
250
|
-
end
|
|
88
|
+
# @since 2.1.0
|
|
89
|
+
def attribute_change(attr)
|
|
90
|
+
[changed_attributes[attr], attributes[attr]] if attribute_changed?(attr)
|
|
251
91
|
end
|
|
252
92
|
end
|
|
253
93
|
end
|
data/lib/mongoid/document.rb
CHANGED
|
@@ -6,7 +6,6 @@ module Mongoid #:nodoc:
|
|
|
6
6
|
module Document
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
include Mongoid::Components
|
|
9
|
-
include Mongoid::MultiDatabase
|
|
10
9
|
|
|
11
10
|
included do
|
|
12
11
|
attr_reader :new_record
|
|
@@ -125,13 +124,15 @@ module Mongoid #:nodoc:
|
|
|
125
124
|
#
|
|
126
125
|
# @return [ Document ] A new document.
|
|
127
126
|
def initialize(attrs = nil)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
building do
|
|
128
|
+
@new_record = true
|
|
129
|
+
@attributes = apply_default_attributes
|
|
130
|
+
process(attrs) do
|
|
131
|
+
yield self if block_given?
|
|
132
|
+
identify
|
|
133
|
+
end
|
|
134
|
+
run_callbacks(:initialize) { self }
|
|
133
135
|
end
|
|
134
|
-
run_callbacks(:initialize) { self }
|
|
135
136
|
end
|
|
136
137
|
|
|
137
138
|
# Reloads the +Document+ attributes from the database. If the document has
|
|
@@ -150,8 +151,8 @@ module Mongoid #:nodoc:
|
|
|
150
151
|
raise Errors::DocumentNotFound.new(self.class, id) if reloaded.nil?
|
|
151
152
|
end
|
|
152
153
|
@attributes = {}.merge(reloaded || {})
|
|
154
|
+
changed_attributes.clear
|
|
153
155
|
apply_default_attributes
|
|
154
|
-
reset_modifications
|
|
155
156
|
tap do
|
|
156
157
|
relations.keys.each do |name|
|
|
157
158
|
if instance_variable_defined?("@#{name}")
|
|
@@ -161,24 +162,6 @@ module Mongoid #:nodoc:
|
|
|
161
162
|
end
|
|
162
163
|
end
|
|
163
164
|
|
|
164
|
-
# Remove a child document from this parent. If an embeds one then set to
|
|
165
|
-
# nil, otherwise remove from the embeds many.
|
|
166
|
-
#
|
|
167
|
-
# This is called from the +RemoveEmbedded+ persistence command.
|
|
168
|
-
#
|
|
169
|
-
# @example Remove the child.
|
|
170
|
-
# document.remove_child(child)
|
|
171
|
-
#
|
|
172
|
-
# @param [ Document ] child The child (embedded) document to remove.
|
|
173
|
-
def remove_child(child)
|
|
174
|
-
name = child.metadata.name
|
|
175
|
-
if child.embedded_one?
|
|
176
|
-
remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
|
|
177
|
-
else
|
|
178
|
-
send(name).delete(child)
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
|
|
182
165
|
# Return an array with this +Document+ only in it.
|
|
183
166
|
#
|
|
184
167
|
# @example Return the document in an array.
|
|
@@ -198,11 +181,12 @@ module Mongoid #:nodoc:
|
|
|
198
181
|
#
|
|
199
182
|
# @return [ Hash ] A hash of all attributes in the hierarchy.
|
|
200
183
|
def as_document
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
184
|
+
attributes.tap do |attrs|
|
|
185
|
+
relations.each_pair do |name, meta|
|
|
186
|
+
if meta.embedded?
|
|
187
|
+
relation = send(name, false, :continue => false)
|
|
188
|
+
attrs[name] = relation.as_document unless relation.blank?
|
|
189
|
+
end
|
|
206
190
|
end
|
|
207
191
|
end
|
|
208
192
|
end
|
|
@@ -222,12 +206,26 @@ module Mongoid #:nodoc:
|
|
|
222
206
|
unless klass.include?(Mongoid::Document)
|
|
223
207
|
raise ArgumentError, 'A class which includes Mongoid::Document is expected'
|
|
224
208
|
end
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
209
|
+
klass.new.tap do |became|
|
|
210
|
+
became.instance_variable_set('@attributes', @attributes)
|
|
211
|
+
became.instance_variable_set('@errors', @errors)
|
|
212
|
+
became.instance_variable_set('@new_record', new_record?)
|
|
213
|
+
became.instance_variable_set('@destroyed', destroyed?)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
private
|
|
218
|
+
|
|
219
|
+
# Implement this for calls to flatten on array.
|
|
220
|
+
#
|
|
221
|
+
# @example Get the document as an array.
|
|
222
|
+
# document.to_ary
|
|
223
|
+
#
|
|
224
|
+
# @return [ nil ] Always nil.
|
|
225
|
+
#
|
|
226
|
+
# @since 2.1.0
|
|
227
|
+
def to_ary
|
|
228
|
+
nil
|
|
231
229
|
end
|
|
232
230
|
|
|
233
231
|
module ClassMethods #:nodoc:
|
|
@@ -260,7 +258,7 @@ module Mongoid #:nodoc:
|
|
|
260
258
|
allocate.tap do |doc|
|
|
261
259
|
doc.instance_variable_set(:@attributes, attributes)
|
|
262
260
|
doc.send(:apply_default_attributes)
|
|
263
|
-
doc
|
|
261
|
+
IdentityMap.set(doc)
|
|
264
262
|
doc.run_callbacks(:initialize) { doc }
|
|
265
263
|
end
|
|
266
264
|
end
|
|
@@ -272,7 +270,7 @@ module Mongoid #:nodoc:
|
|
|
272
270
|
#
|
|
273
271
|
# @return [ Array<Class> ] All subclasses of the current document.
|
|
274
272
|
def _types
|
|
275
|
-
@_type ||= [descendants + [self]].flatten.uniq.map
|
|
273
|
+
@_type ||= [descendants + [self]].flatten.uniq.map { |t| t.to_s }
|
|
276
274
|
end
|
|
277
275
|
|
|
278
276
|
# Set the i18n scope to overwrite ActiveModel.
|