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

我有什么方法可以找出为什么记录没有被删除?该模型有两个验证,都仅在创建时触发。它有一个回调,但如果失败,回调不会阻塞。

我没有回溯或错误要查看。

4

5 回答 5

44

更新:请参阅 Mike Slate 的答案以获得更快的解决方案:https ://stackoverflow.com/a/53872915/171183 。

我遇到了同样的问题,这就是我为弄清楚发生了什么所做的事情......

(TL;DR:底部给出的完整代码清单。)

首先,对于我要销毁的对象的类,我运行它以找出所有关联设置为dependent: :destroy

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

然后我调用了在我的对象上命名的每个关联ary并收集了结果。这将关联名称限制为仅具有实际依赖对象的关联名称:

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

然后我可以尝试销毁这些关联名称返回的每个对象以找到问题对象:

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? }
# ...

然后我可以查看每个问题对象的错误:

problem_objects.map(&:errors)

这就是我终于看到导致破坏失败的错误的地方。从那里开始,它是一个简单的编程问题 (SMOP) 来解决这个问题。

在我的例子中,有一个before_destroy回调阻止destroy 处理我的一个依赖对象关联。为了让以后的调试更简单,我决定开始在 Rails 日志中记录失败回调的错误(除了将错误消息添加到errors.base)。

完整的代码清单:

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)
于 2014-08-02T14:30:18.220 回答
22

我已经遇到过几次这种情况,终于找到了一种简单的方法来确定记录没有被破坏的原因(在 Rails 5.x 中测试)。

只需将调用包装起来即可销毁!在救援块中,查看 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
于 2018-12-20T16:52:14.870 回答
4

此错误通常是由于dependent: :restrict_with_error模型中指定的关联而引发的。在您的模型定义(以及相关的模型定义)中快速搜索此内容,看看是否是这种情况。

于 2016-11-04T16:47:29.413 回答
2

你在哪个版本的 Rails 上?在 Rails 4 中,您可以使用person.destroy!. 如果操作失败,将显示回溯。

于 2013-05-27T06:25:33.640 回答
0

您应该添加一些调试信息,例如 logger.debug 并查看您的日志文件。例如 log/production.log 如果在生产模式下运行等等,你应该能够找出原因。如果没有,您可以在此处发布相关的日志文件部分(例如您正在运行的操作),我们可以为您提供帮助。

于 2013-05-27T06:31:46.440 回答