2012-06-07 21 views
7

Znasz ćwiczenie: niektóre nieprawidłowe dane pojawiają się w produkcyjnej bazie danych i musisz się ich pozbyć. Odpalić konsoli Rails na serwerze produkcyjnym i rodzaju w zapytaniu:Jak wyświetlić podgląd zapytania delete_all lub destroy_all w Railsach

Foo.where(bar: 'baz').all 

przejrzeć zwróconych danych i to, co trzeba usunąć. Następnie wpisz:

Foo.where(bar: 'baz').destroy_all 

A twoje serce zatrzymuje się na sekundę. Po prostu chcesz zobaczyć zapytanie przed uruchomieniem.

Czy jest jakiś sposób to zrobić w Rails? Szukam sposobem podobnym do

Foo.where(bar: 'baz').to_sql 

ale taka, która zwróci DELETE zapytania.

Odpowiedz

1

Po prostu z góry mojej głowy, można uruchomić konsolę w trybie piaskownicy i uruchomić kwerendę usuwania, aby zobaczyć sql. Zmiany zostaną wycofane po wyjściu.

+0

przypuszczam, że tego nie robi naprawdę odpowiedz na twoje pytanie, jeśli naprawdę szukasz komunikatora "to_sql" i. – cdesrosiers

+0

Całkowicie zapomniałem o trybie piaskownicy! Nie jest to dokładnie to, czego szukałem, ale robi dokładnie to, czego potrzebowałem. Szczególnie biorąc pod uwagę, że to, czego szukałem, jest niemożliwe: D –

2

Problem polega na tym, że destroy_all nie uruchamia pojedynczego zapytania SQL. Dokonuje iteracji poprzez mieszanie obiektów, tworzy ich wystąpienia, uruchamia ich wywołania zwrotne, a następnie wywołuje metodę niszczenia obiektu. Railsy nie zostały zbudowane w celu utworzenia tablicy tych zapytań.

Cdesroisiers ma rację, że można przetestować zapytanie w trybie piaskownicy, ale prawdziwym problemem jest to, że po drugie, zgadujesz, że chcesz uruchomić funkcję delete_all, mimo że masz pewność, że dane są kierowane.

Należy rozważyć użycie klejnotu wersji ActiveRecord, takiego jak PaperTrail, jeśli nie chcesz zaufać ActiveRecord, aby poprawnie usunąć obiekty.

+0

Jakie jest uzasadnienie braku implementacji 'delete_all' jako operacji wsadowej Uważałem, że jest dużo tańsze, aby zrobić to w partii, zamiast poważnie traktować wycieczkę do bazy danych. – Bedasso

+2

delete_all jest operacją wsadową. destroy_all robi je jeden po drugim. delete_all istnieje, ponieważ jest szybszy, destroy_all może być przydatny, ponieważ będzie strzelał przed/po zniszczeniu wywołań zwrotnych. –

+0

PaperTrail doskonale nadaje się do użytku w aplikacji, ale musiałem pozbyć się zbędnych danych. Dzięki i tak! –

1

metoda destroy_all jest taka sama jak robi:

Foo.where(bar: 'baz').each { |object| object.destroy } 

Więc SQL staje

DELETE FROM foo WHERE foo.id = your_objects_id_attribute 



Od docs:

def destroy_all(conditions = nil) 
    find(:all, :conditions => conditions).each { |object| object.destroy } 
    end 
+1

Wierzę, że wygenerowany SQL będzie składał się z wielu zapytań DELETE - po jednym na każdy znaleziony obiekt. – mrt