85

残りのリソースの破棄について、破棄操作の続行を許可する前に、いくつかのことを保証したいですか?基本的に、データベースが無効な状態になることに気付いた場合、破棄操作を停止する機能が必要ですか?破棄操作には検証コールバックがないので、破棄操作を受け入れる必要があるかどうかをどのように「検証」するのでしょうか。

4

11 に答える 11

74

キャッチする例外を発生させることができます。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ようになり、返されたときに入力されます。

于 2008-09-23T19:22:37.723 に答える
49

ただのメモ:

レール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
于 2011-07-29T13:54:27.240 に答える
20

それは私が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
于 2016-06-17T11:36:05.277 に答える
6

ActiveRecord の関連付け has_many および has_one では、削除時に関連するテーブル行が確実に削除されるようにする依存オプションを使用できますが、これは通常、データベースが無効になるのを防ぐためではなく、データベースをきれいに保つためです。

于 2008-09-23T22:16:49.957 に答える
5

コントローラーの「if」ステートメントで破棄アクションをラップできます。

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

どこでvalid_destroy? レコードを破棄する条件が満たされた場合に true を返す、モデル クラスのメソッドです。

このような方法を使用すると、ユーザーに削除オプションが表示されないようにすることもできます。これにより、ユーザーが不正な操作を実行できなくなるため、ユーザー エクスペリエンスが向上します。

于 2008-09-24T05:11:09.743 に答える
4

ここのコードを使用して、activerecordでcan_destroyオーバーライドを作成することになりました: https://gist.github.com/andhapp/1761098

class ActiveRecord::Base
  def can_destroy?
    self.class.reflect_on_all_associations.all? do |assoc|
      assoc.options[:dependent] != :restrict || (assoc.macro == :has_one && self.send(assoc.name).nil?) || (assoc.macro == :has_many && self.send(assoc.name).empty?)
    end
  end
end

これには、UI で削除ボタンを非表示/表示することが簡単になるという追加の利点があります。

于 2013-06-17T19:14:16.860 に答える
2

before_destroy コールバックを使用して例外を発生させることもできます。

于 2008-09-23T19:26:17.043 に答える
2

私はこれらのクラスまたはモデルを持っています

class Enterprise < AR::Base
   has_many :products
   before_destroy :enterprise_with_products?

   private

   def empresas_with_portafolios?
      self.portafolios.empty?  
   end
end

class Product < AR::Base
   belongs_to :enterprises
end

エンタープライズを削除すると、このプロセスは、エンタープライズに関連付けられた製品があるかどうかを検証します。 注: 最初に検証するために、クラスの先頭にこれを記述する必要があります。

于 2014-01-10T23:00:20.893 に答える