@@ -68,7 +68,9 @@ def changes
68
68
# @example Move the changes to previous.
69
69
# person.move_changes
70
70
def move_changes
71
+ @changes_before_last_save = @previous_changes
71
72
@previous_changes = changes
73
+ @attributes_before_last_save = @previous_attributes
72
74
@previous_attributes = attributes . dup
73
75
Atomic ::UPDATES . each do |update |
74
76
send ( update ) . clear
@@ -133,6 +135,72 @@ def setters
133
135
mods
134
136
end
135
137
138
+ # Returns the original value of an attribute before the last save.
139
+ #
140
+ # This method is useful in after callbacks to get the original value of
141
+ # an attribute before the save that triggered the callbacks to run.
142
+ #
143
+ # @param [ Symbol | String ] attr The name of the attribute.
144
+ #
145
+ # @return [ Object ] Value of the attribute before the last save.
146
+ def attribute_before_last_save ( attr )
147
+ attr = database_field_name ( attr )
148
+ attributes_before_last_save [ attr ]
149
+ end
150
+
151
+ # Returns the change to an attribute during the last save.
152
+ #
153
+ # @param [ Symbol | String ] attr The name of the attribute.
154
+ #
155
+ # @return [ Array<Object> | nil ] If the attribute was changed, returns
156
+ # an array containing the original value and the saved value, otherwise nil.
157
+ def saved_change_to_attribute ( attr )
158
+ attr = database_field_name ( attr )
159
+ previous_changes [ attr ]
160
+ end
161
+
162
+ # Returns whether this attribute changed during the last save.
163
+ #
164
+ # This method is useful in after callbacks, to see the change
165
+ # in an attribute during the save that triggered the callbacks to run.
166
+ #
167
+ # @param [ String ] attr The name of the attribute.
168
+ # @param **kwargs The optional keyword arguments.
169
+ #
170
+ # @option **kwargs [ Object ] :from The object the attribute was changed from.
171
+ # @option **kwargs [ Object ] :to The object the attribute was changed to.
172
+ #
173
+ # @return [ true | false ] Whether the attribute has changed during the last save.
174
+ def saved_change_to_attribute? ( attr , **kwargs )
175
+ changes = saved_change_to_attribute ( attr )
176
+ return false unless changes . is_a? ( Array )
177
+ if kwargs . key? ( :from ) && kwargs . key? ( :to )
178
+ changes . first == kwargs [ :from ] && changes . last == kwargs [ :to ]
179
+ elsif kwargs . key? ( :from )
180
+ changes . first == kwargs [ :from ]
181
+ elsif kwargs . key? ( :to )
182
+ changes . last == kwargs [ :to ]
183
+ else
184
+ true
185
+ end
186
+ end
187
+
188
+ # Returns whether this attribute change the next time we save.
189
+ #
190
+ # This method is useful in validations and before callbacks to determine
191
+ # if the next call to save will change a particular attribute.
192
+ #
193
+ # @param [ String ] attr The name of the attribute.
194
+ # @param **kwargs The optional keyword arguments.
195
+ #
196
+ # @option **kwargs [ Object ] :from The object the attribute was changed from.
197
+ # @option **kwargs [ Object ] :to The object the attribute was changed to.
198
+ #
199
+ # @return [ true | false ] Whether the attribute change the next time we save.
200
+ def will_save_change_to_attribute? ( attr , **kwargs )
201
+ attribute_changed? ( attr , **kwargs )
202
+ end
203
+
136
204
private
137
205
138
206
# Get attributes of the document before the document was saved.
@@ -142,6 +210,14 @@ def previous_attributes
142
210
@previous_attributes ||= { }
143
211
end
144
212
213
+ def changes_before_last_save
214
+ @changes_before_last_save ||= { }
215
+ end
216
+
217
+ def attributes_before_last_save
218
+ @attributes_before_last_save ||= { }
219
+ end
220
+
145
221
# Get the old and new value for the provided attribute.
146
222
#
147
223
# @example Get the attribute change.
@@ -317,6 +393,9 @@ def create_dirty_change_check(name, meth)
317
393
re_define_method ( "#{ meth } _changed?" ) do |**kwargs |
318
394
attribute_changed? ( name , **kwargs )
319
395
end
396
+ re_define_method ( "will_save_change_to_#{ meth } ?" ) do |**kwargs |
397
+ will_save_change_to_attribute? ( name , **kwargs )
398
+ end
320
399
end
321
400
end
322
401
@@ -350,6 +429,15 @@ def create_dirty_previous_value_accessor(name, meth)
350
429
re_define_method ( "#{ meth } _previously_was" ) do
351
430
attribute_previously_was ( name )
352
431
end
432
+ re_define_method ( "#{ meth } _before_last_save" ) do
433
+ attribute_before_last_save ( name )
434
+ end
435
+ re_define_method ( "saved_change_to_#{ meth } " ) do
436
+ saved_change_to_attribute ( name )
437
+ end
438
+ re_define_method ( "saved_change_to_#{ meth } ?" ) do |**kwargs |
439
+ saved_change_to_attribute? ( name , **kwargs )
440
+ end
353
441
end
354
442
end
355
443
0 commit comments