Rails: зависимый =>: уничтожить VS: зависимый =>: delete_all

192

В направляющих рельсов это описано так:

Объекты будут дополнительно уничтожены, если они связаны с :dependent => :destroy, и удалены, если они связаны с:dependent => :delete_all

Хорошо, круто Но какая разница между уничтожением и удалением? Я попробовал и то, и другое, похоже, делает то же самое.

Сергей
источник

Ответы:

200

Разница в обратном вызове.

Это :delete_allделается непосредственно в вашем приложении и удаляется SQL:

DELETE * FROM users where compagny_id = XXXX

С :destroy, есть экземпляр всех ваших детей. Так что, если вы не можете уничтожить его или если у каждого есть свой :dependent, можно вызвать его обратные вызовы.

shingara
источник
83
Инстанцирование и вызов destroy для каждого из дочерних объектов будут медленными, если у вас много детей (и n ^ 2, если у вас есть внуки и т. Д.). delete_all - это решение типа «взломать его с орбиты», когда вы не заботитесь о / не имеете до / после уничтожения обратных вызовов на моделях.
Райан Бигг
131

В ассоциации моделей Rails вы можете указать :dependentопцию, которая может принимать одну из следующих трех форм:

  • :destroy/:destroy_allСвязанные объекты уничтожаются вместе с этим объектом, вызывая их destroyметод
  • :delete/:delete_allВсе связанные объекты уничтожаются немедленно, без вызова их :destroyметода.
  • :nullifyВнешние ключи всех связанных объектов установлены NULLбез вызова их saveобратных вызовов
Джон Топли
источник
2
См. Api.rubyonrails.org/classes/ActiveRecord/Associations/… (поиск «обнулить») для получения достоверных rdocs.
mrm
21
Начиная с Rails 3.0 это также можно указать :restrict. Если установлено значение: restrict, этот объект не может быть удален, если у него есть какой-либо связанный объект.
RocketR
17
нету :deleteили :destroy_allвариантов по внешнему виду? Опция: зависимый ожидает: destroy,: delete_all,: nullify или: restrict (: delete)
Майк Кэмпбелл
2
@MikeCampbell, :deleteи :destroy_allвариантов не существует. Однако в вызываемых моделях есть методы класса, deleteи destroy_allэто может стать причиной путаницы.
Березовский
@MikeCampbell Вам не хватает еще нескольких параметров, см. Параметр: зависимый должен быть одним из [: destroy,: delete_all,: nullify,: restrict_with_error,: restrict_with_exception]
Правин Мишра
30

Увидеть уничтожает удаляет связанные с ним элементы, где delete_all может удалить несколько данных из собственной таблицы какDELETE * FROM table where field = 'xyz'

: Зависимые возможные варианты:

Управляет тем, что происходит со связанными объектами, когда их владелец уничтожен. Обратите внимание, что они реализованы как обратные вызовы, а Rails выполняет обратные вызовы по порядку. Следовательно, другие подобные обратные вызовы могут влиять на зависимое поведение, а :dependentповедение может влиять на другие обратные вызовы.

:destroy вызывает уничтожение всех связанных объектов.

:delete_all вызывает удаление всех связанных объектов непосредственно из базы данных (поэтому обратные вызовы не будут выполняться).

:nullifyзаставляет внешние ключи быть установленными в NULL. Обратные вызовы не выполняются.

:restrict_with_exception вызывает исключение, если есть какие-либо связанные записи.

:restrict_with_error вызывает добавление ошибки к владельцу, если есть какие-либо связанные объекты.

При использовании с этой :throughопцией, ассоциация в модели соединения должна быть принадлежащей для принадлежности, а удаляемые записи являются записями соединения, а не связанными записями.

Маниш Шривастава
источник
3

На самом деле главное отличие состоит в том, что никакие обратные вызовы не будут вызываться при :delete_allиспользовании. Но когда используется :destroyстек обратных вызовов ( :after_destroy,:after_commit ...) будет запущен.

Следовательно, если у вас есть touch:объявления в моделях, которые вы удаляете, то лучше использовать dependent: :delete_allскорее «зависимый:: уничтожить».

atlascoder
источник