How do I 'validate' on destroy in rails

前端 未结 11 1764
你的背包
你的背包 2020-11-28 06:33

On destruction of a restful resource, I want to guarantee a few things before I allow a destroy operation to continue? Basically, I want the ability to stop the destroy oper

相关标签:
11条回答
  • 2020-11-28 07:28

    The ActiveRecord associations has_many and has_one allows for a dependent option that will make sure related table rows are deleted on delete, but this is usually to keep your database clean rather than preventing it from being invalid.

    0 讨论(0)
  • 2020-11-28 07:31

    You can raise an exception which you then catch. Rails wraps deletes in a transaction, which helps matters.

    For example:

    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
    

    Alternatively you can use the before_destroy callback. This callback is normally used to destroy dependent records, but you can throw an exception or add an error instead.

    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 will now return false, and myBooking.errors will be populated on return.

    0 讨论(0)
  • just a note:

    For rails 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
    
    0 讨论(0)
  • 2020-11-28 07:35

    You can wrap the destroy action in an "if" statement in the controller:

    def destroy # in controller context
      if (model.valid_destroy?)
        model.destroy # if in model context, use `super`
      end
    end
    

    Where valid_destroy? is a method on your model class that returns true if the conditions for destroying a record are met.

    Having a method like this will also let you prevent the display of the delete option to the user - which will improve the user experience as the user won't be able to perform an illegal operation.

    0 讨论(0)
  • 2020-11-28 07:39

    You can also use the before_destroy callback to raise an exception.

    0 讨论(0)
提交回复
热议问题