@@ -141,8 +141,7 @@ def really_destroy!
141
141
end
142
142
if dependent_reflections . any?
143
143
dependent_reflections . each do |name , reflection |
144
- association_data = self . send ( name )
145
- # has_one association can return nil
144
+ association_data = self . send ( name ) || get_soft_deleted_has_one ( reflection )
146
145
# .paranoid? will work for both instances and classes
147
146
next unless association_data && association_data . paranoid?
148
147
if reflection . collection?
@@ -187,41 +186,36 @@ def restore_associated_records(recovery_window_range = nil)
187
186
end
188
187
189
188
destroyed_associations . each do |association |
190
- association_data = send ( association . name )
189
+ association_data = send ( association . name ) || get_soft_deleted_has_one ( association )
191
190
192
- unless association_data . nil?
193
- if association_data . paranoid?
194
- if association . collection?
195
- association_data . only_deleted . each do |record |
196
- record . restore ( :recursive => true , :recovery_window_range => recovery_window_range )
197
- end
198
- else
199
- association_data . restore ( :recursive => true , :recovery_window_range => recovery_window_range )
191
+ if association_data && association_data . paranoid?
192
+ restore_options = { :recursive => true , :recovery_window_range => recovery_window_range }
193
+ if association . collection?
194
+ association_data . only_deleted . each do |record |
195
+ record . restore ( restore_options )
200
196
end
201
- end
202
- end
203
-
204
- if association_data . nil? && association . macro . to_s == "has_one"
205
- association_class_name = association . klass . name
206
- association_foreign_key = association . foreign_key
207
-
208
- if association . type
209
- association_polymorphic_type = association . type
210
- association_find_conditions = { association_polymorphic_type => self . class . name . to_s , association_foreign_key => self . id }
211
197
else
212
- association_find_conditions = { association_foreign_key => self . id }
213
- end
214
-
215
- association_class = association_class_name . constantize
216
- if association_class . paranoid?
217
- association_class . only_deleted . where ( association_find_conditions ) . first
218
- . try! ( :restore , recursive : true , :recovery_window_range => recovery_window_range )
198
+ association_data . restore ( restore_options )
219
199
end
220
200
end
221
201
end
222
202
223
203
clear_association_cache if destroyed_associations . present?
224
204
end
205
+
206
+ # For soft deleted objects, has_one associations will return nil if the
207
+ # associated object is also soft deleted. Because of this, we have to do the
208
+ # object look-up explicitly. This method takes an association, and if it is
209
+ # a has_one and the object referenced by the assocation uses paranoia, it
210
+ # returns the object referenced by the association. Otherwise, it returns nil.
211
+ def get_soft_deleted_has_one ( association )
212
+ return nil unless association . macro . to_s == "has_one"
213
+
214
+ association_find_conditions = { association . foreign_key => self . id }
215
+ association_find_conditions [ association . type ] = self . class . name if association . type
216
+
217
+ association . klass . only_deleted . find_by ( association_find_conditions ) if association . klass . paranoid?
218
+ end
225
219
end
226
220
227
221
ActiveSupport . on_load ( :active_record ) do
@@ -301,7 +295,7 @@ def build_relation(klass, *args)
301
295
class UniquenessValidator < ActiveModel ::EachValidator
302
296
prepend UniquenessParanoiaValidator
303
297
end
304
-
298
+
305
299
class AssociationNotSoftDestroyedValidator < ActiveModel ::EachValidator
306
300
def validate_each ( record , attribute , value )
307
301
# if association is soft destroyed, add an error
0 commit comments