Ответы:
В основном destroy
запускает любые обратные вызовы для модели, а delete
не делает.
Из Rails API :
ActiveRecord::Persistence.delete
Удаляет запись в базе данных и замораживает этот экземпляр, чтобы отразить, что не следует вносить изменения (так как они не могут быть сохранены). Возвращает замороженный экземпляр.
Строка просто удаляется с помощью оператора SQL DELETE для первичного ключа записи, и обратные вызовы не выполняются.
Чтобы обеспечить обратные вызовы объекта before_destroy и after_destroy или любые: зависимые параметры ассоциации, используйте #destroy.
ActiveRecord::Persistence.destroy
Удаляет запись в базе данных и замораживает этот экземпляр, чтобы отразить, что не следует вносить изменения (так как они не могут быть сохранены).
Существует ряд обратных вызовов, связанных с уничтожением. Если обратный вызов before_destroy возвращает false, действие отменяется, а destroy возвращает false. См. ActiveRecord :: Callbacks для получения дополнительной информации.
model#before_destroy
что может использоваться для остановки окончательного destroy()
вызова при определенных условиях.
delete
удалит только текущую запись объекта из БД, но не связанные с ней дочерние записи из БД.
destroy
удалит текущую запись объекта из базы данных, а также связанную с ней дочернюю запись из базы данных.
Их использование действительно имеет значение:
Если ваши родительские объекты имеют общие дочерние объекты, то вызов destroy
определенного родительского объекта приведет к удалению дочерних объектов, которые совместно используются другими несколькими родителями.
destroy
это потомки , а не дети : согласно документации, destroy «создает новый объект из атрибутов, а затем вызывает для него уничтожение». rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Когда вы вызываете destroy
или destroy_all
на ActiveRecord
объекте,ActiveRecord
инициируется процесс «уничтожения», он анализирует класс, который вы удаляете, определяет, что он должен делать для зависимостей, проходит проверки и т. Д.
Когда вы вызываете объект delete
или обращаетесь delete_all
к нему, он ActiveRecord
просто пытается выполнить DELETE FROM tablename WHERE conditions
запрос к базе данных, не выполняя никаких других ActiveRecord
задач.
Да, между этими двумя методами есть существенное различие. Используйте delete_all, если хотите, чтобы записи быстро удалялись без вызова обратных вызовов модели.
Если вам небезразличны обратные вызовы ваших моделей, тогда используйте destroy_all
Из официальных документов
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (условие = ноль) публично
Уничтожает условия сопоставления записей, создавая каждую запись и вызывая ее метод уничтожения. Выполняются обратные вызовы каждого объекта (в том числе: зависимые параметры ассоциации и методы Observer before_destroy / after_destroy). Возвращает коллекцию объектов, которые были уничтожены; каждый будет заморожен, чтобы отразить, что никакие изменения не должны быть сделаны (так как их нельзя сохранить).
Примечание. Создание, обратный вызов и удаление каждой записи может занять много времени, если вы удаляете много записей одновременно. Он генерирует по крайней мере один запрос SQL DELETE для каждой записи (или, возможно, больше, для обеспечения ваших обратных вызовов). Если вы хотите быстро удалить много строк, не обращая внимания на их ассоциации или обратные вызовы, используйте вместо этого delete_all.
В основном «удалить» отправляет запрос непосредственно в базу данных, чтобы удалить запись. В этом случае Rails не знает, какие атрибуты находятся в записи, которую он удаляет, и нет ли каких-либо обратных вызовов (таких как before_destroy
).
Метод "destroy" берет переданный идентификатор, выбирает модель из базы данных, используя метод "find", а затем вызывает destroy для этого. Это означает, что обратные вызовы запускаются.
Вы можете использовать «удалить», если не хотите, чтобы выполнялись обратные вызовы или вы хотите повысить производительность. В противном случае (и большую часть времени) вы захотите использовать «уничтожить».
Уже много ответов; хотел прыгнуть с немного больше.
Для has_many, destroy и destroy_all всегда будут вызывать метод уничтожения удаляемых записей, чтобы выполнялись обратные вызовы. Однако delete и delete_all будут выполнять удаление в соответствии со стратегией, указанной параметром: зависимый, или, если параметр не указан, то он будет следовать стратегии по умолчанию. Стратегия по умолчанию - ничего не делать (оставить внешние ключи с установленными родительскими идентификаторами), за исключением has_many: through, где стратегией по умолчанию является delete_all (удалить записи объединения, не выполняя их обратные вызовы).
delete
Verbage работает по- разному для ActiveRecord::Association.has_many
и ActiveRecord::Base
. В последнем случае delete выполнит SQL DELETE
и пропустит все проверки / обратные вызовы. Первый будет выполнен на основе :dependent
опции, переданной в ассоциацию. Однако, во время тестирования, я нашел следующий побочный эффект , когда обратные вызовы пробежались только delete
и неdelete_all
dependent: :destroy
Пример:
class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end
class Child < ApplicationRecord
belongs_to :parent
before_destroy -> { puts "before_destroy callback" }
end
> child.delete # Ran without callbacks
Child Destroy (99.6ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 21]]
> parent.children.delete(other_child) # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = $1 [["parent_id", 1]]