Відповіді:
В основному destroy
запускає будь-які зворотні виклики на моделі, поки delete
немає.
З API Rails :
ActiveRecord::Persistence.delete
Видаляє запис у базі даних та заморожує цей примірник, щоб відобразити, що ніяких змін не слід вносити (оскільки їх не можна зберегти). Повертає заморожений екземпляр.
Рядок просто видаляється оператором SQL DELETE в первинному ключі запису, і зворотні виклики не виконуються.
Щоб застосувати зворотні виклики до_destroy та after_destroy або будь-які: залежні параметри асоціації, використовуйте #destroy.
ActiveRecord::Persistence.destroy
Видаляє запис у базі даних та заморожує цей примірник, щоб відобразити, що ніяких змін не слід вносити (оскільки їх не можна зберегти).
Існує серія зворотних викликів, пов’язаних із знищенням. Якщо зворотний виклик before_destroy повертається помилково, дія скасовується і знищується return false. Детальнішу інформацію див. У розділі ActiveRecord :: зворотні дзвінки.
model#before_destroy
що може бути застосовано для зупинки кінцевого destroy()
дзвінка за певних умов.
delete
буде видаляти тільки поточний запис об'єкта з db, але не пов'язані з ним дочірні записи з db.
destroy
видалить поточний запис об'єкта з db, а також пов'язаний з ним дочірній запис з db.
Їх використання справді має значення:
Якщо ваші декілька батьківських об'єктів мають спільні дочірні об’єкти, то виклик 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
запит проти db, не виконуючи ніяких інших ActiveRecord
завдань рівня.
Так, є велика різниця між двома методами. Використовуйте delete_all, якщо ви хочете, щоб записи швидко видалялися без виклику зворотних викликів моделей.
Якщо ви дбаєте про зворотні дзвінки ваших моделей, тоді використовуйте kill_all
Від офіційних док
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
знищити_all (умови = нуль) громадськість
Знищує записи, що відповідають умовам, інстанціюючи кожен запис і викликаючи його метод знищення. Зворотні виклики кожного об'єкта виконуються (у тому числі: залежні параметри асоціації та методи спостерігача before_destroy / after_destroy). Повертає колекцію предметів, які були знищені; кожен буде заморожений, щоб відображати, що ніяких змін не слід вносити (оскільки їх не можна зберегти).
Примітка: миттєве завантаження, виконання зворотних дзвінків та видалення кожної записи може зайняти багато часу, коли ви видаляєте багато записів одночасно. Він генерує щонайменше один SQL DELETE-запит на запис (або, можливо, більше, щоб примусити відкликати дзвінки). Якщо ви хочете швидко видалити багато рядків, не турбуючись про їх асоціації чи зворотні дзвінки, замість цього скористайтеся delete_all.
В основному "delete" надсилає запит безпосередньо в базу даних, щоб видалити запис. У цьому випадку Rails не знає, які атрибути є у записі, який він видаляє, а також немає зворотних викликів (наприклад, before_destroy
).
Метод "знищити" приймає переданий ідентифікатор, виймає модель з бази даних методом "знайти", а потім викликає знищення на цьому. Це означає, що зворотні виклики спрацьовують.
Ви хочете використовувати "delete", якщо ви не хочете, щоб спрацьовували зворотні дзвінки або ви хочете покращити продуктивність. В іншому випадку (і більшу частину часу) ви захочете використовувати "знищити".
Дуже багато відповідей; хотілося трохи більше стрибнути.
Для has_many, знищити і kill_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]]