Что делают Rails с обоими: depend =>: destroy и cascade delete/nullify/restrict

Я пытаюсь решить, как лучше всего настроить (если вообще) внешние ограничения ключа для моего приложения rails. У меня есть модель Response, которая belongs_to a Prompt. Я хотел бы использовать :dependent => :destroy для вызова destroy на каждый Response, который принадлежит удаленному Prompt, и я пытаюсь решить, какое ограничение на удаление я должен разместить на моем внешнем ключе.

Короче говоря, мне нужен совет о том, как я могу лучше всего использовать как метод destroy для зависимых объектов, так и ограничения внешнего ключа, чтобы гарантировать, что крут не накапливается и не отражает логическую структуру хранящихся данных. Несколько предыдущих вопросов, таких как Должен ли я использовать ON DELETE CASCADE,: dependent = > : уничтожить или оба? и Rails: удалить каскад против зависимого уничтожения спросил, что было лучше, но они не очень много говорят о том, как два варианта взаимодействуют и в каком порядке они срабатывают или кажутся расплывчатыми в этом вопросе.

Как я вижу, соображения, похоже, разбиваются на несколько частей:

  • Вызывает ли вызов :dependent => :destroy сначала на зависимые объекты перед удалением родителя из базы данных, поэтому уничтожение будет вызываться на этих объектах, даже если я использую каскадное удаление?
  • Удаляет ли :dependent => :destroy зависимые объекты из базы данных до (или в транзакции) с удалением родителя из базы данных? Другими словами, если я устанавливаю каскад для аннулирования, база данных в конечном итоге опустошает ссылки на дочерние объекты до их удаления?

  • Удаляются ли в результате исходных вариантов уничтожения и привязки :dependent => :destroy, завернутых в транзакцию, или, к сожалению, при кратковременных сбоях в базе данных, если я не устанавливаю каскадное удаление?

    /li >
  • Наконец, будет :dependent => :destroy гарантировать, что родительский объект будет удален из базы данных, если я использую ограничение как параметр внешнего ключа on_delete?

Ответ 1

При dependent: :destroy в транзакции rails сначала уничтожает все зависимости, а только потом удаляет саму запись.

Может быть условие гонки: если зависимая запись была добавлена сразу после того, как рельсы прочитали коллекцию для уничтожения, но еще не удалили родителя - она может быть оставлена. Позвольте назвать эти "записи о состоянии гонки" ниже.

  1. да, вы можете использовать dependent: :destroy и on delete cascade, таким образом, некоторые дочерние элементы (состояния гонки) могут быть удалены без обратных вызовов. Если обратные вызовы являются обязательными - on delete restrict вместе с некоторыми блокировками и явное дочернее удаление может быть лучше. Это похоже на validates :some_field, uniqueness: true который лучше поддерживать уникальным индексом, только база данных может обеспечить согласованность данных.

  2. поскольку родитель удаляется последним, on delete nullify не будет мешать (вы получите аннулированные записи о состоянии гонки)

  3. там транзакция, оборачивающая все удаляемые, могут быть оставлены только записи о состоянии гонки

  4. on delete restrict по dependent: :destroy будет срабатывать только для записей условий гонки (и откатывать всю транзакцию), но если условий гонки не было - рельсы удачно удалят все.