Odpowiedzi:
Zasadniczo destroy
uruchamia wszelkie wywołania zwrotne w modelu, podczas gdy delete
nie.
ActiveRecord::Persistence.delete
Usuwa rekord w bazie danych i zawiesza to wystąpienie, aby pokazać, że nie należy wprowadzać żadnych zmian (ponieważ nie można ich utrwalić). Zwraca zamrożoną instancję.
Wiersz jest po prostu usuwany za pomocą instrukcji SQL DELETE na kluczu podstawowym rekordu i żadne wywołania zwrotne nie są wykonywane.
Aby wymusić wywołania zwrotne before_destroy i after_destroy obiektu lub dowolne: zależne opcje asocjacji, użyj #destroy.
ActiveRecord::Persistence.destroy
Usuwa rekord w bazie danych i zawiesza to wystąpienie, aby pokazać, że nie należy wprowadzać żadnych zmian (ponieważ nie można ich utrwalić).
Istnieje szereg wywołań zwrotnych związanych ze zniszczeniem. Jeśli wywołanie zwrotne before_destroy zwróci wartość false, akcja zostanie anulowana, a zniszczenie zwróci wartość false. Zobacz ActiveRecord :: Callbacki w celu uzyskania dalszych szczegółów.
model#before_destroy
możliwość zatrzymania destroy()
połączenia końcowego pod pewnymi warunkami.
delete
usunie tylko bieżący rekord obiektu z db, ale nie skojarzy z nim powiązanych rekordów potomnych.
destroy
usunie bieżący rekord obiektu z db, a także powiązany z nim rekord potomny z db.
Ich użycie naprawdę ma znaczenie:
Jeśli wiele obiektów nadrzędnych korzysta ze wspólnych obiektów podrzędnych, wówczas wywołanie destroy
określonego obiektu nadrzędnego spowoduje usunięcie obiektów podrzędnych, które są współużytkowane przez innych wielu rodziców.
destroy
są potomkowie , a nie dzieci : zgodnie z dokumentacją zniszcz „tworzy nowy obiekt z atrybutów, a następnie wywołuje na nim zniszczenie”. rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Podczas wywoływania destroy
lub destroy_all
na ActiveRecord
obiekcie ActiveRecord
inicjowany jest proces „niszczenia”, analizuje usuwaną klasę, określa, co powinien zrobić dla zależności, uruchamia sprawdzanie poprawności itp.
Podczas wywoływania delete
lub delete_all
na obiekcie, ActiveRecord
po prostu próbuje uruchomić DELETE FROM tablename WHERE conditions
zapytanie względem bazy danych, nie wykonując żadnych innych ActiveRecord
zadań na tym samym poziomie.
Tak, istnieje zasadnicza różnica między dwiema metodami Użyj delete_all, jeśli chcesz, aby rekordy były szybko usuwane bez wywoływania wywołań zwrotnych modelu
Jeśli zależy Ci na wywołaniach zwrotnych swoich modeli, użyj funkcji destroy_all
Z oficjalnych dokumentów
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (warunki = zero) public
Niszczy rekordy spełniające warunki, tworząc instancję każdego rekordu i wywołując jego metodę niszczenia. Wywołania zwrotne każdego obiektu są wykonywane (w tym: opcje powiązania zależnego oraz metody Observer before_destroy / after_destroy Observer). Zwraca kolekcję zniszczonych obiektów; każdy zostanie zamrożony, aby odzwierciedlić, że nie należy wprowadzać żadnych zmian (ponieważ nie można ich utrwalić).
Uwaga: Tworzenie instancji, wykonywanie oddzwonienia i usuwanie każdego rekordu może być czasochłonne, gdy usuwasz wiele rekordów jednocześnie. Generuje co najmniej jedno zapytanie SQL DELETE na rekord (lub więcej, aby wymusić wywołania zwrotne). Jeśli chcesz szybko usunąć wiele wierszy, bez obawy o ich powiązania lub wywołania zwrotne, użyj delete_all.
Zasadniczo „usuń” wysyła zapytanie bezpośrednio do bazy danych w celu usunięcia rekordu. W takim przypadku Railsy nie wiedzą, jakie atrybuty znajdują się w rekordzie, który usuwa, ani nie ma żadnych wywołań zwrotnych (takich jak before_destroy
).
Metoda „zniszczyć” pobiera przekazany identyfikator, pobiera model z bazy danych przy użyciu metody „znajdź”, a następnie wywołuje na nim funkcję zniszczenia. Oznacza to, że wywołania zwrotne są wyzwalane.
Możesz użyć opcji „usuń”, jeśli nie chcesz, aby wywołania zwrotne były wyzwalane lub chcesz poprawić wydajność. W przeciwnym razie (i przez większość czasu) będziesz chciał użyć opcji „zniszczyć”.
Wiele odpowiedzi już; chciałem wskoczyć na trochę więcej.
W przypadku has_many, zniszcz i zniszcz_wszystko zawsze wywoła metodę zniszczenia usuwanego rekordu (rekordów), aby wywołać wywołania zwrotne. Jednak delete i delete_all albo wykonają usunięcie zgodnie ze strategią określoną przez opcję: zależną, lub jeśli nie zostanie podana opcja: zależna, będzie postępować zgodnie z domyślną strategią. Domyślną strategią jest nic nie robić (pozostawić klucze obce z ustawionymi identyfikatorami nadrzędnymi), z wyjątkiem has_many: through, gdzie domyślną strategią jest delete_all (usuń rekordy łączenia, bez uruchamiania wywołań zwrotnych).
delete
Verbage działa inaczej na ActiveRecord::Association.has_many
i ActiveRecord::Base
. W tym drugim przypadku delete wykona SQL DELETE
i obejdzie wszystkie sprawdzania poprawności / wywołania zwrotne. Ten pierwszy zostanie wykonany na podstawie :dependent
opcji przekazanej do powiązania. Jednak podczas testowania znalazłem następujący efekt uboczny, w którym wywołania zwrotne były uruchamiane tylko dla, delete
a nie dladelete_all
dependent: :destroy
Przykład:
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]]