我如何在 Rails 中“驗證”銷毀 (How do I 'validate' on destroy in rails)


問題描述

我如何在 Rails 中“驗證”銷毀 (How do I 'validate' on destroy in rails)

在銷毀 RESTful 資源時,我想在允許銷毀操作繼續之前保證幾件事?基本上,如果我注意到這樣做會使數據庫處於無效狀態,我希望能夠停止銷毀操作?銷毀操作沒有驗證回調,那麼如何“驗證”是否應該接受銷毀操作?


參考解法

方法 1:

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.

方法 2:

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

方法 3:

It is what I did with 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

方法 4:

State of affairs as of Rails 6:

This works:

before_destroy :ensure_something, prepend: true do
  throw(:abort) if errors.present?
end

private

def ensure_something
  errors.add(:field, "This isn't a good idea..") if something_bad
end

validate :validate_test, on: :destroy doesn't work: https://github.com/rails/rails/issues/32376

Since Rails 5 throw(:abort) is required to cancel execution: https://makandracards.com/makandra/20301‑cancelling‑the‑activerecord‑callback‑chain

prepend: true is required so that dependent: :destroy doesn't run before the validations are executed: https://github.com/rails/rails/issues/3458

You can fish this together from other answers and comments, but I found none of them to be complete.

As a sidenote, many used a has_many relation as an example where they want to make sure not to delete any records if it would create orphaned records. This can be solved much more easily:

has_many :entities, dependent: :restrict_with_error

方法 5:

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.

(by Stephen CagleAirsource LtdworkdreamerRaphael Monteirothisismydesigngo minimal)

參考文件

  1. How do I 'validate' on destroy in rails (CC BY‑SA 2.5/3.0/4.0)

#Callback #ruby-on-rails #ruby






相關問題

將 C++ 函數指針設置為 C# 委託 (set C++ function pointer as C# delegate)

YouTube(注入)視頻結束回調 (YouTube (injected) video ends callback)

我如何在 Rails 中“驗證”銷毀 (How do I 'validate' on destroy in rails)

Як я магу рэалізаваць зваротныя выклікі на іншы сервер у C# (How can I implement callbacks to another server in c#)

顯示等待通知,直到回調從線程返回 (Show waiting notification till callback returns from thread)

應用程序未通過文本服務框架 DLL 檢測輸入語言更改 (Application not detecting input language changes via Text Service Framework DLL)

回調參數名稱 (Callback parameters name)

我是否以正確的方式考慮回調? (Am I thinking about Callbacks the right way?)

MSMQ 異步異常行為 - .NET 4.0 與 .NET 2.0 (MSMQ asynchronous exception behavior - .NET 4.0 vs .NET 2.0)

參數連接問題。我該如何處理 (parameter connection problem. How can I deal with this)

如何在 JavaScript 中實現動態回調參數 (How can I achieve dynamic callback arguments in JavaScript)

回調警告:回調錯誤創建破折號數據表 (Callback warning: Callback error creating dash' DataTable)







留言討論