在破坏一个宁静的资源时,我想在我允许销毁操作继续之前保证一些东西?基本上,如果我注意到这样做会将数据库置于无效状态,我希望能够停止销毁操作吗?在销毁操作上没有验证回调,那么如何"验证"是否应该接受销毁操作?
您可以引发一个异常然后捕获的异常.Rails在事务中包装删除,这有助于解决问题.
例如:
class Booking < ActiveRecord::Base has_many :booking_payments .... def destroy raise "Cannot delete booking with payments" unless booking_payments.count == 0 # ... ok, go ahead and destroy super end end
或者,您可以使用before_destroy回调.此回调通常用于销毁相关记录,但您可以抛出异常或添加错误.
def before_destroy return true if booking_payments.count == 0 errors.add :base, "Cannot delete booking with payments" # or errors.add_to_base in Rails 2 false # Rails 5 throw(:abort) end
myBooking.destroy
现在将返回false,并将myBooking.errors
在返回时填充.
只是一个说明:
对于铁轨3
class Booking < ActiveRecord::Base before_destroy :booking_with_payments? private def booking_with_payments? errors.add(:base, "Cannot delete booking with payments") unless booking_payments.count == 0 errors.blank? #return false, to not destroy the element, otherwise, it will delete. end
这是我用Rails 5做的:
before_destroy do cannot_delete_with_qrcodes throw(:abort) if errors.present? end def cannot_delete_with_qrcodes errors.add(:base, 'Cannot delete shop with qrcodes') if qrcodes.any? end
ActiveRecord关联has_many和has_one允许使用依赖选项,以确保在删除时删除相关的表行,但这通常是为了保持数据库清洁而不是阻止它无效.
您可以将destroy操作包装在控制器的"if"语句中:
def destroy # in controller context if (model.valid_destroy?) model.destroy # if in model context, use `super` end end
哪里有valid_destroy?是模型类上的一种方法,如果满足销毁记录的条件,则返回true.
使用这样的方法还可以阻止向用户显示删除选项 - 这将改善用户体验,因为用户将无法执行非法操作.