/ / Dlaczego ActiveRecord udostępnia .delete_all, a nie .truncate? - rubin na szynach, aktywny zapis

Dlaczego ActiveRecord zapewnia .delete_all, a nie .Truncate? - ruby-on-rails, activerecord

Wydaje się dziwne, że muszę ręcznie wykonać SQL, aby użyć polecenia TRUNCATE. Czy jest w tym coś złego, przed czym chroni mnie DHH?

Odpowiedzi:

10 dla odpowiedzi № 1

Za pomocą TRUNCATE w niektórych bazach danych nie uruchamia wyzwalaczy. Za pomocą DELETE dla każdego wiersza nadal będą uruchamiane wyzwalacze. TRUNCATE również nie można go wycofać, więc jeśli zrobiłeś .destroy_all w transakcji spowoduje to usunięcie wszystkich danych, nawet jeśli spróbujesz wycofać.

Tak, jesteś chroniony przed skutkami obcięcia.


3 dla odpowiedzi № 2

Zakładając, że używasz MySQL lub Postgre, a nie SQlite3 (który nie obsługuje TRUNCATE), możesz dodać następującą metodę do swojego modelu.

def self.truncate
self.connection_pool.with_connection { |c| c.truncate(table_name) }
end

Zauważ, że nie wywołałoby to ActiveRecordoddzwanianie. Są lepsze sposoby na to, aby nie wiązać kodu z konkretną implementacją DB, ale nawet to jest lepsze niż samodzielne pisanie SQL.


1 dla odpowiedzi nr 3

Istnieje wiele przypadków użycia dla TRUNCATEi moim zdaniem podane tutaj odpowiedzi są bardzo niewystarczające. Na przykładzie Postgres:

  • TRUNCATE jest zdecydowanie bezpieczny dla transakcji w niektórych RDBMS, jak już zauważyli jsears. Można go wycofać, przynajmniej w Postgres. Czy szyny nie powinny być db-agnostyczne i pozwalają na takie rzeczy?
  • TRUNCATE wykona również BEFORE TRUNCATE lub AFTER TRUNCATE wyzwalacze w Postgresie. Jeśli spodziewasz się DELETE uruchomić spust TRUNCATE to twoja wina projektowa!
  • TRUNCATE działa znacznie szybciej niż DELETE szczególnie w przypadku dużych zestawów danych, ponieważ jest to pojedyncza krótka instrukcja DDL.
  • W architekturze MVCC w Postgres, TRUNCATE usuwa wszystkie wzdęcia indeksu i tabeli.

Z tych powodów jest dla mnie szalone, że Rails nie obsługuje TRUNCATE. Nie, nie sądzę, aby podane powody były dobre.


-3 dla odpowiedzi № 4

Spójrz na Model.destroy_all i aktywny rekord: zależny =>: zniszcz relacje. Jeśli nie określisz: zależne =>: destory, niektóre z wartości domyślnych to ustawienie relacji na zero, ale nie zniszczenie rekordu.