我已经查阅了Ruby on Rails的指南,但似乎无法弄清如何防止删除具有关联子项的父项记录。例如,如果我的数据库中有客户,每个客户可以拥有多个订单,我希望当数据库中存在订单时,阻止删除客户记录。只有没有订单时才能删除客户。
在定义模型之间的关联时,是否有一种方法可以强制执行此行为?
我已经查阅了Ruby on Rails的指南,但似乎无法弄清如何防止删除具有关联子项的父项记录。例如,如果我的数据库中有客户,每个客户可以拥有多个订单,我希望当数据库中存在订单时,阻止删除客户记录。只有没有订单时才能删除客户。
在定义模型之间的关联时,是否有一种方法可以强制执行此行为?
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :restrict # raises ActiveRecord::DeleteRestrictionError
编辑:自Rails 4.1起,:restrict
选项已不再可用,您应该使用:restrict_with_error
或:restrict_with_exception
中的任一选项。
例如:
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :restrict_with_error
你可以在回调函数中实现这个功能:
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
编辑
查看这个答案以获得更好的方法。
dependent: :restrict
是最好的选择。尽管我怀疑在引入dependent restrict之前,这个答案已经被接受了。 - Damien Roche一种可能的方法是在这种情况下避免向用户提供删除链接。
link_to_unless !@customer.orders.empty?
另一种方法是在您的控制器中处理此问题:
if !@customer.orders.empty?
flash[:notice] = "Cannot delete a customer with orders"
render :action => :some_action
end
或者,正如Joe所建议的那样,在此处可以使用before_filters,并且可能是更DRY的方法来完成这项工作,尤其是如果您想要将此类型的行为用于不仅仅是Customer的更多模型。
restrict_with_error
会为相应的属性添加一个 Rails 错误,而restrict_with_exception
则会抛出指定的异常。请参阅 https://edgeguides.rubyonrails.org/association_basics.html#options-for-has-one-dependent。 - codener