destroy
and delete
. It's
quite easy to confuse these two terms, but they are different and after a
while you get used to it.$ rails new bookshelf [...] $ cd bookshelf $ rails generate model book title [...] $ rails generate model author book_id:integer first_name last_name [...] $ rake db:migrate [...] $
app/models/book.rb
class Book < ActiveRecord::Base has_many :authors, dependent: :destroy end
app/models/author.rb
class Author < ActiveRecord::Base belongs_to :book end
destroy
you can remove a record and
any existing dependencies are also taken into account (see for example
:dependent => :destroy
in the section called “Options”). Simply put: to be on the safe side,
it's better to use destroy
because then the Rails
system does more for you.$ rails console Loading development environment (Rails 4.0.0) >> book = Book.create(title: 'Homo faber') (0.1ms) begin transaction SQL (2.2ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 16 Jul 2013 13:30:24 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 16 Jul 2013 13:30:24 UTC +00:00]] (2.2ms) commit transaction => #<Book id: 1, title: "Homo faber", created_at: "2013-07-16 13:30:24", updated_at: "2013-07-16 13:30:24"> >> Book.count (0.3ms) SELECT COUNT(*) FROM "books" => 1 >> book.destroy (0.2ms) begin transaction Author Load (0.2ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = ? [["book_id", 1]] SQL (0.3ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 1]] (0.6ms) commit transaction => #<Book id: 1, title: "Homo faber", created_at: "2013-07-16 13:30:24", updated_at: "2013-07-16 13:30:24"> >> Book.count (0.4ms) SELECT COUNT(*) FROM "books" => 0 >>
dependent: :destroy
in the
Book model, we can also automatically remove all authors:>> 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, 16 Jul 2013 13:31:11 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 16 Jul 2013 13:31:11 UTC +00:00]] (1.9ms) commit transaction (0.1ms) begin transaction SQL (0.5ms) INSERT INTO "authors" ("book_id", "created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?) [["book_id", 2], ["created_at", Tue, 16 Jul 2013 13:31:11 UTC +00:00], ["first_name", "Max"], ["last_name", "Frisch"], ["updated_at", Tue, 16 Jul 2013 13:31:11 UTC +00:00]] (1.0ms) commit transaction => #<Author id: 1, book_id: 2, first_name: "Max", last_name: "Frisch", created_at: "2013-07-16 13:31:11", updated_at: "2013-07-16 13:31:11"> >> Author.count (0.4ms) SELECT COUNT(*) FROM "authors" => 1 >> Book.first.destroy Book Load (0.3ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT 1 (0.1ms) begin transaction Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = ? [["book_id", 2]] SQL (0.3ms) DELETE FROM "authors" WHERE "authors"."id" = ? [["id", 1]] SQL (0.1ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 2]] (2.1ms) commit transaction => #<Book id: 2, title: "Homo faber", created_at: "2013-07-16 13:31:11", updated_at: "2013-07-16 13:31:11"> >> Author.count (0.4ms) SELECT COUNT(*) FROM "authors" => 0 >>
frozen?
:>> book = Book.create(title: 'Homo faber') (0.1ms) begin transaction SQL (0.6ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 16 Jul 2013 13:32:30 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 16 Jul 2013 13:32:30 UTC +00:00]] (2.0ms) commit transaction => #<Book id: 3, title: "Homo faber", created_at: "2013-07-16 13:32:30", updated_at: "2013-07-16 13:32:30"> >> book.destroy (0.1ms) begin transaction Author Load (0.2ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = ? [["book_id", 3]] SQL (0.4ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 3]] (1.9ms) commit transaction => #<Book id: 3, title: "Homo faber", created_at: "2013-07-16 13:32:30", updated_at: "2013-07-16 13:32:30"> >> Book.count (0.2ms) SELECT COUNT(*) FROM "books" => 0 >> book => #<Book id: 3, title: "Homo faber", created_at: "2013-07-16 13:32:30", updated_at: "2013-07-16 13:32:30"> >> book.frozen? => true >>
>> Book.create(title: book.title) (0.1ms) begin transaction SQL (0.5ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 16 Jul 2013 13:33:31 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 16 Jul 2013 13:33:31 UTC +00:00]] (1.7ms) commit transaction => #<Book id: 4, title: "Homo faber", created_at: "2013-07-16 13:33:31", updated_at: "2013-07-16 13:33:31"> >> exit $
delete
you can remove a record
directly from the database. Any dependencies to other records in the
model are not taken into
account. The method delete
only deletes that one
row in the database and nothing else.delete
:$ rake db:reset [...] $ rails console Loading development environment (Rails 4.0.0) >> Book.create(title: 'Homo faber').authors.create(first_name: 'Max', last_name: 'Frisch') (0.1ms) begin transaction SQL (2.2ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 16 Jul 2013 13:35:49 UTC +00:00], ["title", "Homo faber"], ["updated_at", Tue, 16 Jul 2013 13:35:49 UTC +00:00]] (2.5ms) commit transaction (0.0ms) begin transaction SQL (0.4ms) INSERT INTO "authors" ("book_id", "created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?) [["book_id", 1], ["created_at", Tue, 16 Jul 2013 13:35:49 UTC +00:00], ["first_name", "Max"], ["last_name", "Frisch"], ["updated_at", Tue, 16 Jul 2013 13:35:49 UTC +00:00]] (0.9ms) commit transaction => #<Author id: 1, book_id: 1, first_name: "Max", last_name: "Frisch", created_at: "2013-07-16 13:35:49", updated_at: "2013-07-16 13:35:49"> >> Author.count (0.3ms) SELECT COUNT(*) FROM "authors" => 1 >> Book.last.delete Book Load (0.2ms) SELECT "books".* FROM "books" ORDER BY "books"."id" DESC LIMIT 1 SQL (2.9ms) DELETE FROM "books" WHERE "books"."id" = 1 => #<Book id: 1, title: "Homo faber", created_at: "2013-07-16 13:35:49", updated_at: "2013-07-16 13:35:49"> >> Author.count (0.4ms) SELECT COUNT(*) FROM "authors" => 1 >> Book.count (0.4ms) SELECT COUNT(*) FROM "books" => 0 >> exit $
destroy
, an object also gets frozen
when you use delete
(see the section called “destroy”). The record is already removed from the
database, but the object itself is still there.Thank you for your support and the visibility by linking to this website on Twitter and Facebook. That helps a lot!