Odpowiedzi:
Zasadniczo destroyuruchamia wszelkie wywołania zwrotne w modelu, podczas gdy deletenie.
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_destroymoż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 destroyokreślonego obiektu nadrzędnego spowoduje usunięcie obiektów podrzędnych, które są współużytkowane przez innych wielu rodziców.
destroysą 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 destroylub destroy_allna ActiveRecordobiekcie ActiveRecordinicjowany jest proces „niszczenia”, analizuje usuwaną klasę, określa, co powinien zrobić dla zależności, uruchamia sprawdzanie poprawności itp.
Podczas wywoływania deletelub delete_allna obiekcie, ActiveRecordpo prostu próbuje uruchomić DELETE FROM tablename WHERE conditionszapytanie względem bazy danych, nie wykonując żadnych innych ActiveRecordzadań 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).
deleteVerbage działa inaczej na ActiveRecord::Association.has_manyi ActiveRecord::Base. W tym drugim przypadku delete wykona SQL DELETEi obejdzie wszystkie sprawdzania poprawności / wywołania zwrotne. Ten pierwszy zostanie wykonany na podstawie :dependentopcji 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, deletea 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]]