如果父项有子记录,如何防止删除父项?

Rob*_*Rob 45 model ruby-on-rails associations

我已经查看了Ruby on Rails指南,我似乎无法弄清楚如果有父级记录,如果有人删除父记录.例如.如果我的数据库有CUSTOMERS并且每个客户可以有多个ORDERS,我想阻止有人在数据库中有任何订单时删除客户.如果客户没有订单,他们应该只能删除客户.

在定义模型之间的关联以强制执行此行为时,有没有办法?

小智 100

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => :restrict # raises ActiveRecord::DeleteRestrictionError
Run Code Online (Sandbox Code Playgroud)

编辑:从Rails 4.1开始,:restrict不是一个有效的选项,而是你应该使用:restrict_with_error:restrict_with_exception

例如.:

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => :restrict_with_error
Run Code Online (Sandbox Code Playgroud)

  • 限制信息可以自定义吗? (2认同)
  • 是否可以更新此答案以反映Rails 4.1及更高版本中的更改?"删除了对已弃用选项的支持:限制:依赖于关联." http://edgeguides.rubyonrails.org/4_1_release_notes.html.:dependent选项必须是[:destroy,:delete_all,:nullify,:restrict_with_error,:restrict_with_exception]之一 (2认同)

zet*_*tic 47

您可以在回调中执行此操作:

class Customer < ActiveRecord::Base
  has_many :orders
  before_destroy :check_for_orders

  private

  def check_for_orders
    if orders.count > 0
      errors.add_to_base("cannot delete customer while orders exist")
      return false
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

编辑

看到这个答案有一个更好的方法来做到这一点.

  • 这是最好的方法.它是最干净的,如果我正在处理你的代码,它正是我寻找这样一个过滤器的地方.在回调中返回"false"是告诉rails不要继续执行操作的原因. (5认同)
  • 您可能需要考虑使用错误#add(:base,msg). (3认同)
  • 这不是最好的方法.根据@ Mauro的回答,一个简单的`dependent :: restrict`是.虽然我怀疑在引入依赖限制之前接受了这个答案. (3认同)
  • @Zenph Yup,:dependent =>:restrict是后来添加的,是更好的解决方案. (3认同)
  • 我为各种模型中需要此功能的应用程序创建了一个小型ActiveRecord插件:https://github.com/Florent2/prevent_destroy_if_any (2认同)