4.12. Einen Datensatz löschen
Mit
destroy
können Sie einen Datensatz
löschen und dabei werden auch vorhandene Abhängigkeiten beachtet (siehe z.
B.
:dependent => :destroy
in
„Optionen“). Vereinfacht kann man sagen: Lieber
destroy
nehmen; das ist sicherer, weil das
Rails-System dann mehr mitdenkt.
Legen wir einmal einen Datensatz an und löschen ihn danach
wieder:
MacBook:bookshelf xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > book = Book.create(:title => 'Homo faber')
(0.1ms) begin transaction
SQL (6.2ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 08 May 2012 08:10:58 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 08 May 2012 08:10:58 UTC +00:00]]
(1.3ms) commit transaction
=> #<Book id: 1, title: "Homo faber", created_at: "2012-05-08 08:10:58", updated_at: "2012-05-08 08:10:58">
1.9.3p194 :002 > Book.all
Book Load (0.3ms) SELECT "books".* FROM "books"
=> [#<Book id: 1, title: "Homo faber", created_at: "2012-05-08 08:10:58", updated_at: "2012-05-08 08:10:58">]
1.9.3p194 :003 > book.destroy
(0.1ms) begin transaction
Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = 1
SQL (0.3ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 1]]
(1.1ms) commit transaction
=> #<Book id: 1, title: "Homo faber", created_at: "2012-05-08 08:10:58", updated_at: "2012-05-08 08:10:58">
1.9.3p194 :004 > Book.all
Book Load (0.3ms) SELECT "books".* FROM "books"
=> []
1.9.3p194 :005 >
Da wir im Book Model die Option
:dependent =>
:destroy
benutzen, können wir beim Löschen auch automatisch alle
Autoren mitlöschen:
1.9.3p194 :005 > Book.create(:title => 'Homo faber').authors.create(:first_name => 'Max', :last_name => 'Frisch')
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 08 May 2012 08:46:14 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 08 May 2012 08:46:14 UTC +00:00]]
(3.7ms) commit transaction
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "authors" ("book_id", "created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?) [["book_id", 2], ["created_at", Tue, 08 May 2012 08:46:14 UTC +00:00], ["first_name", "Max"], ["last_name", "Frisch"], ["updated_at", Tue, 08 May 2012 08:46:14 UTC +00:00]]
(0.8ms) commit transaction
=> #<Author id: 1, book_id: 2, first_name: "Max", last_name: "Frisch", created_at: "2012-05-08 08:46:14", updated_at: "2012-05-08 08:46:14">
1.9.3p194 :006 > Book.all
Book Load (0.3ms) SELECT "books".* FROM "books"
=> [#<Book id: 2, title: "Homo faber", created_at: "2012-05-08 08:46:14", updated_at: "2012-05-08 08:46:14">]
1.9.3p194 :007 > Author.all
Author Load (0.2ms) SELECT "authors".* FROM "authors"
=> [#<Author id: 1, book_id: 2, first_name: "Max", last_name: "Frisch", created_at: "2012-05-08 08:46:14", updated_at: "2012-05-08 08:46:14">]
1.9.3p194 :008 > Book.first.destroy
Book Load (0.3ms) SELECT "books".* FROM "books" LIMIT 1
(0.1ms) begin transaction
Author Load (0.2ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = 2
SQL (0.4ms) DELETE FROM "authors" WHERE "authors"."id" = ? [["id", 1]]
SQL (0.1ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 2]]
(2.4ms) commit transaction
=> #<Book id: 2, title: "Homo faber", created_at: "2012-05-08 08:46:14", updated_at: "2012-05-08 08:46:14">
1.9.3p194 :009 > Author.all
Author Load (0.3ms) SELECT "authors".* FROM "authors"
=> []
1.9.3p194 :010 >
Bitte denken Sie beim Löschen immer an den Unterschied des Inhaltes
der Datenbank und des Wertes des aktuell gelöschten Objektes. Die Instanz
wird nach dem Löschen des Datenbank-Feldes
frozen (eingefroren). Sie ist also in der
Datenbank nicht mehr, aber im Programm noch da, kann aber dort nicht
verändert werden. Lesen geht aber. Zum Überprüfen gibt es die Methode
frozen?
:
1.9.3p194 :010 > book = Book.create(:title => 'Homo faber')
(0.1ms) begin transaction
SQL (2.6ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 08 May 2012 08:15:01 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 08 May 2012 08:15:01 UTC +00:00]]
(3.5ms) commit transaction
=> #<Book id: 3, title: "Homo faber", created_at: "2012-05-08 08:15:01", updated_at: "2012-05-08 08:15:01">
1.9.3p194 :011 > book.destroy
(0.1ms) begin transaction
Author Load (0.3ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = 3
SQL (0.4ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 3]]
(2.5ms) commit transaction
=> #<Book id: 3, title: "Homo faber", created_at: "2012-05-08 08:15:01", updated_at: "2012-05-08 08:15:01">
1.9.3p194 :012 > Book.all
Book Load (0.2ms) SELECT "books".* FROM "books"
=> [#<Book id: 2, title: "Homo faber", created_at: "2012-05-08 08:13:09", updated_at: "2012-05-08 08:13:09">]
1.9.3p194 :013 > book
=> #<Book id: 3, title: "Homo faber", created_at: "2012-05-08 08:15:01", updated_at: "2012-05-08 08:15:01">
1.9.3p194 :014 > book.frozen?
=> true
1.9.3p194 :015 >
Der Datensatz ist also in der Datenbank gelöscht, aber das Objekt
mit allen Daten ist noch im laufenden Ruby-Programm vorhanden. Könnten wir
damit den gesamten Datensatz wiederbeleben? Ja, allerdings ist das dann
ein neuer Datensatz:
1.9.3p194 :018 > Book.create(:title => book.title)
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 08 May 2012 08:34:04 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 08 May 2012 08:34:04 UTC +00:00]]
(3.4ms) commit transaction
=> #<Book id: 4, title: "Homo faber", created_at: "2012-05-08 08:34:04", updated_at: "2012-05-08 08:34:04">
1.9.3p194 :019 > exit
MacBook:bookshelf xyz$
Mit delete
können Sie einen Datensatz
direkt in der Datenbank löschen. Dabei werden keine Abhängigkeiten zu
anderen Datensätzen im Model
beachtet. Die Methode delete
löscht also nur die
eine Zeile in der Datenbank und sonst nichts.
Erstellen wir ein Buch mit einem Autor und löschen das Buch danach
mit
delete
:
MacBook:bookshelf xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > Book.create(:title => 'Homo faber').authors.create(:first_name => 'Max', :last_name => 'Frisch')
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 08 May 2012 08:41:08 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 08 May 2012 08:41:08 UTC +00:00]]
(3.5ms) commit transaction
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "authors" ("book_id", "created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?) [["book_id", 6], ["created_at", Tue, 08 May 2012 08:41:08 UTC +00:00], ["first_name", "Max"], ["last_name", "Frisch"], ["updated_at", Tue, 08 May 2012 08:41:08 UTC +00:00]]
(1.0ms) commit transaction
=> #<Author id: 3, book_id: 6, first_name: "Max", last_name: "Frisch", created_at: "2012-05-08 08:41:08", updated_at: "2012-05-08 08:41:08">
1.9.3p194 :002 > Book.last.delete
Book Load (0.3ms) SELECT "books".* FROM "books" ORDER BY "books"."id" DESC LIMIT 1
SQL (3.7ms) DELETE FROM "books" WHERE "books"."id" = 6
=> #<Book id: 6, title: "Homo faber", created_at: "2012-05-08 08:41:08", updated_at: "2012-05-08 08:41:08">
1.9.3p194 :003 > Author.exists?(3)
Author Exists (0.3ms) SELECT 1 FROM "authors" WHERE "authors"."id" = 3 LIMIT 1
=> true
1.9.3p194 :004 > ruby-1.9.2-p0 > exit
MacBook:bookshelf xyz$
Es wird zwar der Datensatz des Buches 'Homo faber' gelöscht, aber
der Autor ist noch in der Datenbank gespeichert.
Wie bei
destroy
, geht auch bei
delete
ein Objekt nach dem
delete
in den
frozen-Status (siehe
„destroy“). Der Datensatz ist also in der
Datenbank bereits gelöscht, aber das Objekt an sich existiert noch.