thorsson-mongo_mapper 0.8.2
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/LICENSE +20 -0
- data/README.rdoc +27 -0
- data/bin/mmconsole +60 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/scopes.rb +52 -0
- data/lib/mongo_mapper.rb +79 -0
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +41 -0
- data/lib/mongo_mapper/embedded_document.rb +31 -0
- data/lib/mongo_mapper/exceptions.rb +27 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/plugins.rb +16 -0
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations.rb +97 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +124 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +29 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +127 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +110 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +126 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +241 -0
- data/lib/mongo_mapper/plugins/clone.rb +19 -0
- data/lib/mongo_mapper/plugins/descendants.rb +17 -0
- data/lib/mongo_mapper/plugins/dirty.rb +120 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
- data/lib/mongo_mapper/plugins/equality.rb +17 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +15 -0
- data/lib/mongo_mapper/plugins/keys.rb +309 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +55 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +112 -0
- data/lib/mongo_mapper/plugins/pagination.rb +14 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +53 -0
- data/lib/mongo_mapper/plugins/querying.rb +176 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +76 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +15 -0
- data/lib/mongo_mapper/plugins/validations.rb +50 -0
- data/lib/mongo_mapper/support/descendant_appends.rb +45 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
- data/test/functional/associations/test_in_array_proxy.rb +319 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
- data/test/functional/associations/test_many_documents_proxy.rb +575 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +67 -0
- data/test/functional/associations/test_one_proxy.rb +182 -0
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +44 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +151 -0
- data/test/functional/test_dirty.rb +163 -0
- data/test/functional/test_document.rb +253 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +210 -0
- data/test/functional/test_identity_map.rb +506 -0
- data/test/functional/test_indexes.rb +42 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +416 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +175 -0
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_userstamps.rb +27 -0
- data/test/functional/test_validations.rb +342 -0
- data/test/models.rb +233 -0
- data/test/test_active_model_lint.rb +13 -0
- data/test/test_helper.rb +104 -0
- data/test/unit/associations/test_base.rb +212 -0
- data/test/unit/associations/test_proxy.rb +105 -0
- data/test/unit/serializers/test_json_serializer.rb +202 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +213 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +644 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_key.rb +185 -0
- data/test/unit/test_keys.rb +55 -0
- data/test/unit/test_mongo_mapper.rb +110 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/test_rails.rb +181 -0
- data/test/unit/test_rails_compatibility.rb +52 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +544 -0
- metadata +316 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Caching
|
5
|
+
module InstanceMethods
|
6
|
+
def cache_key(*suffixes)
|
7
|
+
cache_key = case
|
8
|
+
when new?
|
9
|
+
"#{self.class.name}/new"
|
10
|
+
when timestamp = self[:updated_at]
|
11
|
+
"#{self.class.name}/#{id}-#{timestamp.to_s(:number)}"
|
12
|
+
else
|
13
|
+
"#{self.class.name}/#{id}"
|
14
|
+
end
|
15
|
+
cache_key += "/#{suffixes.join('/')}" unless suffixes.empty?
|
16
|
+
cache_key
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Almost all of this callback stuff is pulled directly from ActiveSupport
|
3
|
+
# in the interest of support rails 2 and 3 at the same time and is the
|
4
|
+
# same copyright as rails.
|
5
|
+
module MongoMapper
|
6
|
+
module Plugins
|
7
|
+
module Callbacks
|
8
|
+
def self.configure(model)
|
9
|
+
model.class_eval do
|
10
|
+
define_callbacks(
|
11
|
+
:before_save, :after_save,
|
12
|
+
:before_create, :after_create,
|
13
|
+
:before_update, :after_update,
|
14
|
+
:before_validation, :after_validation,
|
15
|
+
:before_validation_on_create, :after_validation_on_create,
|
16
|
+
:before_validation_on_update, :after_validation_on_update,
|
17
|
+
:before_destroy, :after_destroy,
|
18
|
+
:validate_on_create, :validate_on_update,
|
19
|
+
:validate
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def define_callbacks(*callbacks)
|
26
|
+
callbacks.each do |callback|
|
27
|
+
class_eval <<-"end_eval"
|
28
|
+
def self.#{callback}(*methods, &block)
|
29
|
+
callbacks = CallbackChain.build(:#{callback}, *methods, &block)
|
30
|
+
@#{callback}_callbacks ||= CallbackChain.new
|
31
|
+
@#{callback}_callbacks.concat callbacks
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.#{callback}_callback_chain
|
35
|
+
@#{callback}_callbacks ||= CallbackChain.new
|
36
|
+
|
37
|
+
if superclass.respond_to?(:#{callback}_callback_chain)
|
38
|
+
CallbackChain.new(
|
39
|
+
superclass.#{callback}_callback_chain +
|
40
|
+
@#{callback}_callbacks
|
41
|
+
)
|
42
|
+
else
|
43
|
+
@#{callback}_callbacks
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end_eval
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
def valid?
|
53
|
+
action = new? ? 'create' : 'update'
|
54
|
+
run_callbacks(:before_validation)
|
55
|
+
run_callbacks("before_validation_on_#{action}".to_sym)
|
56
|
+
result = super
|
57
|
+
run_callbacks("after_validation_on_#{action}".to_sym)
|
58
|
+
run_callbacks(:after_validation)
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
# Overriding validatable's valid_for_group? to integrate validation callbacks
|
63
|
+
def valid_for_group?(group) #:nodoc:
|
64
|
+
errors.clear
|
65
|
+
run_before_validations
|
66
|
+
run_callbacks(:validate)
|
67
|
+
new? ? run_callbacks(:validate_on_create) : run_callbacks(:validate_on_update)
|
68
|
+
self.class.validate_children(self, group)
|
69
|
+
self.validate_group(group)
|
70
|
+
errors.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
def destroy
|
74
|
+
run_callbacks(:before_destroy)
|
75
|
+
result = super
|
76
|
+
run_callbacks(:after_destroy)
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
def run_callbacks(kind, options={}, &block)
|
81
|
+
callback_chain_method = "#{kind}_callback_chain"
|
82
|
+
return unless self.class.respond_to?(callback_chain_method)
|
83
|
+
self.class.send(callback_chain_method).run(self, options, &block)
|
84
|
+
self.embedded_associations.each do |association|
|
85
|
+
if association.one?
|
86
|
+
self.send(association.name).run_callbacks(kind, options, &block)
|
87
|
+
else
|
88
|
+
self.send(association.name).each do |document|
|
89
|
+
document.run_callbacks(kind, options, &block)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
def create_or_update(*args)
|
97
|
+
run_callbacks(:before_save)
|
98
|
+
if result = super
|
99
|
+
run_callbacks(:after_save)
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
def create(*args)
|
105
|
+
run_callbacks(:before_create)
|
106
|
+
result = super
|
107
|
+
run_callbacks(:after_create)
|
108
|
+
result
|
109
|
+
end
|
110
|
+
|
111
|
+
def update(*args)
|
112
|
+
run_callbacks(:before_update)
|
113
|
+
result = super
|
114
|
+
run_callbacks(:after_update)
|
115
|
+
result
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class CallbackChain < Array
|
120
|
+
def self.build(kind, *methods, &block)
|
121
|
+
methods, options = extract_options(*methods, &block)
|
122
|
+
methods.map! { |method| Callback.new(kind, method, options) }
|
123
|
+
new(methods)
|
124
|
+
end
|
125
|
+
|
126
|
+
def run(object, options={}, &terminator)
|
127
|
+
enumerator = options[:enumerator] || :each
|
128
|
+
|
129
|
+
unless block_given?
|
130
|
+
send(enumerator) { |callback| callback.call(object) }
|
131
|
+
else
|
132
|
+
send(enumerator) do |callback|
|
133
|
+
result = callback.call(object)
|
134
|
+
break result if terminator.call(result, object)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# TODO: Decompose into more Array like behavior
|
140
|
+
def replace_or_append!(chain)
|
141
|
+
if index = index(chain)
|
142
|
+
self[index] = chain
|
143
|
+
else
|
144
|
+
self << chain
|
145
|
+
end
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
149
|
+
def find(callback, &block)
|
150
|
+
select { |c| c == callback && (!block_given? || yield(c)) }.first
|
151
|
+
end
|
152
|
+
|
153
|
+
def delete(callback)
|
154
|
+
super(callback.is_a?(Callback) ? callback : find(callback))
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
def self.extract_options(*methods, &block)
|
159
|
+
methods.flatten!
|
160
|
+
options = methods.extract_options!
|
161
|
+
methods << block if block_given?
|
162
|
+
return methods, options
|
163
|
+
end
|
164
|
+
|
165
|
+
def extract_options(*methods, &block)
|
166
|
+
self.class.extract_options(*methods, &block)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class Callback
|
171
|
+
attr_reader :kind, :method, :identifier, :options
|
172
|
+
|
173
|
+
def initialize(kind, method, options={})
|
174
|
+
@kind = kind
|
175
|
+
@method = method
|
176
|
+
@identifier = options[:identifier]
|
177
|
+
@options = options
|
178
|
+
end
|
179
|
+
|
180
|
+
def ==(other)
|
181
|
+
case other
|
182
|
+
when Callback
|
183
|
+
(self.identifier && self.identifier == other.identifier) || self.method == other.method
|
184
|
+
else
|
185
|
+
(self.identifier && self.identifier == other) || self.method == other
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def eql?(other)
|
190
|
+
self == other
|
191
|
+
end
|
192
|
+
|
193
|
+
def dup
|
194
|
+
self.class.new(@kind, @method, @options.dup)
|
195
|
+
end
|
196
|
+
|
197
|
+
def hash
|
198
|
+
if @identifier
|
199
|
+
@identifier.hash
|
200
|
+
else
|
201
|
+
@method.hash
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def call(*args, &block)
|
206
|
+
evaluate_method(method, *args, &block) if should_run_callback?(*args)
|
207
|
+
rescue LocalJumpError
|
208
|
+
raise ArgumentError,
|
209
|
+
"Cannot yield from a Proc type filter. The Proc must take two " +
|
210
|
+
"arguments and execute #call on the second argument."
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
def evaluate_method(method, *args, &block)
|
215
|
+
case method
|
216
|
+
when Symbol
|
217
|
+
object = args.shift
|
218
|
+
object.send(method, *args, &block)
|
219
|
+
when String
|
220
|
+
eval(method, args.first.instance_eval { binding })
|
221
|
+
when Proc, Method
|
222
|
+
method.call(*args, &block)
|
223
|
+
else
|
224
|
+
if method.respond_to?(kind)
|
225
|
+
method.send(kind, *args, &block)
|
226
|
+
else
|
227
|
+
raise ArgumentError,
|
228
|
+
"Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
|
229
|
+
"a block to be invoked, or an object responding to the callback method."
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def should_run_callback?(*args)
|
235
|
+
[options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
|
236
|
+
![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Clone
|
5
|
+
module InstanceMethods
|
6
|
+
def initialize_copy(other)
|
7
|
+
@_new = true
|
8
|
+
@_destroyed = false
|
9
|
+
default_id_value({})
|
10
|
+
self.attributes = other.attributes.clone.except(:_id).inject({}) do |hash, entry|
|
11
|
+
key, value = entry
|
12
|
+
hash[key] = value.duplicable? ? value.clone : value
|
13
|
+
hash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Descendants
|
5
|
+
module ClassMethods
|
6
|
+
def inherited(descendant)
|
7
|
+
descendants << descendant
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def descendants
|
12
|
+
@descendants ||= []
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Dirty
|
5
|
+
module InstanceMethods
|
6
|
+
def method_missing(method, *args, &block)
|
7
|
+
if method.to_s =~ /(_changed\?|_change|_will_change!|_was)$/
|
8
|
+
method_suffix = $1
|
9
|
+
key = method.to_s.gsub(method_suffix, '')
|
10
|
+
|
11
|
+
if key_names.include?(key)
|
12
|
+
case method_suffix
|
13
|
+
when '_changed?'
|
14
|
+
key_changed?(key)
|
15
|
+
when '_change'
|
16
|
+
key_change(key)
|
17
|
+
when '_will_change!'
|
18
|
+
key_will_change!(key)
|
19
|
+
when '_was'
|
20
|
+
key_was(key)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def changed?
|
31
|
+
!changed_keys.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
def changed
|
35
|
+
changed_keys.keys
|
36
|
+
end
|
37
|
+
|
38
|
+
def changes
|
39
|
+
changed.inject({}) { |h, key| h[key] = key_change(key); h }
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(*args)
|
43
|
+
super
|
44
|
+
changed_keys.clear if args.first.blank? || !new?
|
45
|
+
end
|
46
|
+
|
47
|
+
def save(*args)
|
48
|
+
if status = super
|
49
|
+
changed_keys.clear
|
50
|
+
end
|
51
|
+
status
|
52
|
+
end
|
53
|
+
|
54
|
+
def save!(*args)
|
55
|
+
status = super
|
56
|
+
changed_keys.clear
|
57
|
+
status
|
58
|
+
end
|
59
|
+
|
60
|
+
def reload(*args)
|
61
|
+
document = super
|
62
|
+
changed_keys.clear
|
63
|
+
document
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def clone_key_value(key)
|
68
|
+
value = read_key(key)
|
69
|
+
value.duplicable? ? value.clone : value
|
70
|
+
rescue TypeError, NoMethodError
|
71
|
+
value
|
72
|
+
end
|
73
|
+
|
74
|
+
def changed_keys
|
75
|
+
@changed_keys ||= {}
|
76
|
+
end
|
77
|
+
|
78
|
+
def key_changed?(key)
|
79
|
+
changed_keys.include?(key)
|
80
|
+
end
|
81
|
+
|
82
|
+
def key_change(key)
|
83
|
+
[changed_keys[key], __send__(key)] if key_changed?(key)
|
84
|
+
end
|
85
|
+
|
86
|
+
def key_was(key)
|
87
|
+
key_changed?(key) ? changed_keys[key] : __send__(key)
|
88
|
+
end
|
89
|
+
|
90
|
+
def key_will_change!(key)
|
91
|
+
changed_keys[key] = clone_key_value(key)
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_key(key, value)
|
95
|
+
key = key.to_s
|
96
|
+
|
97
|
+
if changed_keys.include?(key)
|
98
|
+
old = changed_keys[key]
|
99
|
+
changed_keys.delete(key) unless value_changed?(key, old, value)
|
100
|
+
else
|
101
|
+
old = clone_key_value(key)
|
102
|
+
changed_keys[key] = old if value_changed?(key, old, value)
|
103
|
+
end
|
104
|
+
|
105
|
+
super(key, value)
|
106
|
+
end
|
107
|
+
|
108
|
+
def value_changed?(key_name, old, value)
|
109
|
+
key = keys[key_name]
|
110
|
+
|
111
|
+
if key.number? && value.blank?
|
112
|
+
value = nil
|
113
|
+
end
|
114
|
+
|
115
|
+
old != value
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Document
|
5
|
+
module ClassMethods
|
6
|
+
def embeddable?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def new?
|
13
|
+
@_new
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroyed?
|
17
|
+
@_destroyed == true
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload
|
21
|
+
if doc = collection.find_one(:_id => id)
|
22
|
+
tap do |instance|
|
23
|
+
instance.class.associations.each_key do |association_name|
|
24
|
+
send(association_name).reset if respond_to?(association_name)
|
25
|
+
end
|
26
|
+
instance.attributes = doc
|
27
|
+
end
|
28
|
+
else
|
29
|
+
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Used by embedded docs to find root easily without if/respond_to? stuff.
|
34
|
+
# Documents are always root documents.
|
35
|
+
def _root_document
|
36
|
+
self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|