8

before_destroyフック内で、どのオブジェクト(クラス)が呼び出されたかを確認する方法はありdestroyますか?

次の例では、apatientが破壊されると、それらも破壊されますappointments(これが私が望むものです)。ただし、に関連付けられているphysicianものがある場合は、を破棄することを許可したくありません。appointmentsphysician

before_destory繰り返しますが、コールバックでそのようなチェックを行う方法はありますか?そうでない場合、呼び出しの「方向」に基づいて(つまり、誰が呼び出したかに基づいて)この「破壊チェック」を実行する他の方法はありますか?

class Physician < ActiveRecord::Base
  has_many :appointments, dependent: :destroy
  has_many :patients, through: :appointments
end


class Patient < ActiveRecord::Base
  has_many :appointments, dependent: :destroy
  has_many :physicians, through: :appointments
end


class Appointment < ActiveRecord::Base
  belongs_to :patient
  belongs_to :physician

  before_destroy :ensure_not_referenced_by_anything_important

  private

  def ensure_not_referenced_by_anything_important
    unless patients.empty?
      errors.add(:base, 'This physician cannot be deleted because appointments exist.')
      false
    end
  end
end
4

2 に答える 2

21

リレーションシップでは、関連付けのみが削除され、関連付けられたレコードは削除されないdependent: :destroyことに注意してください(つまり、結合レコードは削除されますが、関連付けられたレコードは削除されません)。したがって、を削除すると、は削除され、は削除されません。APIドキュメントの詳細な説明をお読みください。has_many :throughpatientappointmentphysician

以下の関連する段落を貼り付けました。

何が削除されますか?

ここには潜在的な落とし穴があります。関連付けにはhas_and_belongs_to_manyhas_many :through関連するレコードだけでなく、結合テーブルにもレコードがあります。では、これらの削除メソッドの1つを呼び出す場合、正確に何を削除する必要がありますか?

答えは、関連付けの削除は、必ずしも関連付けられたオブジェクト自体ではなく、所有者と関連付けられたオブジェクトの間のリンクを削除することであると想定されているということです。したがって、とを使用するhas_and_belongs_to_manyhas_many :through、結合レコードは削除されますが、関連するレコードは削除されません。

これについて考えると、これは理にかなっています。呼び出すpost.tags.delete(Tag.find_by_name('food'))場合は、タグ自体をデータベースから削除するのではなく、foodタグをからリンク解除する必要があります。post

于 2013-02-24T07:37:56.127 に答える
11

言うだけ:

class Physician < ActiveRecord::Base
  has_many :appointments, dependent: :restrict_with_exception
  has_many :patients, through: :appointments
end

に注意してくださいdependent: :restrict_with_exception。これにより、Active Recordは、予定レコードに関連付けられている医師レコードの破棄を拒否します。

APIドキュメント関連付けの基本ガイドを参照してください。

于 2012-04-06T08:28:39.153 に答える