Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find out why I couldn't #destroy() a record?

person = Person.find(4123) person.destroy #=> false 

What ways do I have to find out why the record wasn't deleted? The model has two validations, both trigger on create only. It has one callback, but the callback doesn't block if it fails.

I have no traceback or errors to look at.

like image 708
krainboltgreene Avatar asked May 27 '13 06:05

krainboltgreene


People also ask

Whats the meaning of I couldn t?

The definition of couldn't is could not. An example of couldn't is a woman saying she was not able to wear white to a wedding. contraction.

How do you use couldn t?

In statements, we use "can't" for present tense, and "couldn't" for past tense. Examples, "I can't help you right now." "He can't come to the phone." "We couldn't finish all the food." "She couldn't find the stapler." So, "can't" is used to refer to impossible things in the present.

What's the meaning of I couldn't make it?

phrase. If you cannot make it, you are unable to attend an event that you have been invited to. 'I can't make it,' she said.


2 Answers

Update: See Mike Slate's answer for a quicker solution: https://stackoverflow.com/a/53872915/171183.

I ran into this same issue and here's what I've done to figure out what's going on...

(TL;DR: Complete code listing given at bottom.)

First, for the class of the object I'm trying to destroy, I ran this to figure out what all associations are set as dependent: :destroy:

ary =    <MyClass>.reflect_on_all_associations.select { |a|      a.options[:dependent] == :destroy    }.map(&:name) 

Then I called each of the associations named in ary on my object and collected the results. This limits the association names to only those that actually have dependent objects:

ary.select! { |association_name|    <my_object>.send(association_name).present?  } 

Then I can attempt to destroy each of the objects returned by these association names to find the problem object(s):

associated_objects =    ary.each_with_object([]) { |association_name, acc|      acc.concat(<my_object>.send(association_name))   }  problem_objects =   associated_objects.select { |obj| obj.destroy; obj.errors.any? } # ... 

I then could look at the errors on each problem object:

problem_objects.map(&:errors) 

And that's where I finally saw the error that was causing the destroy to fail. From there it was a Simple Matter Of Programming (SMOP) to fix the issue.

In my case, there was a before_destroy callback preventing destroy from working on one of my dependent object associations. To make this simpler to debug in the future, I've decided to start logging an error to the Rails log on failed callbacks (in addition to adding the error message to errors.base).

Complete code listing:

my_object = <your_object_here>  ary =    my_object.class.reflect_on_all_associations.select { |a|      a.options[:dependent] == :destroy    }.map(&:name)  ary.select! { |association_name| my_object.send(association_name).present? }  associated_objects =    ary.flat_map { |association_name| my_object.send(association_name) }  problem_objects =   associated_objects.select { |obj| obj.destroy; obj.errors.any? }  problem_objects.map(&:errors) 
like image 174
pdobb Avatar answered Oct 12 '22 13:10

pdobb


I've run into this a few times now, and have finally come across a simple means of identifying the reason the record was not destroyed (tested in Rails 5.x).

Simply wrap the call to destroy! in a rescue block, and look at error.record.errors.

begin   person = Person.find(4123)   person.destroy! #=> Note the exclamation mark which will cause an error if it fails rescue ActiveRecord::RecordNotDestroyed => error   puts "errors that prevented destruction: #{error.record.errors}" end 
like image 31
Mike State Avatar answered Oct 12 '22 15:10

Mike State