はじめに
(多分)Rails 6 に追加された新機能を試す第76段。 今回は、 delete_by destroy_by
編です。
Rails 6 では、 ActvieRecord に delete_by
と destroy_by
が追加されました。
引数に条件を指定して、レコードを削除することができるようになりました。
Ruby 2.6.3, Rails 6.0.0.rc2 で確認しました。
Rails 6.0.0.rc2 は gem install rails -v 6.0.0rc2 --prerelease
でインストールできます。
(確認は、Rails 6.0.0 リリース前に実施したものです。)
$ rails --version
Rails 6.0.0.rc2
プロジェクトを作る
$ bin/rails new rails_sandbox
$ cd rails_sandbox
Library と Book モデルを作る
Library は複数の Book オブジェクトを保持します。
$ bin/rails g model library name
$ bin/rails g model book title libray:references
Library モデルを修正する
has_many
関係を追加します。
class Library < ApplicationRecord
has_many :books, dependent: :destroy
end
seed データを作る
Library, Book ともに複数のデータを作成します。
Library.create(
[
{
name: 'Tokyo',
books: Book.create(
[
{ title: 'Programming Ruby' },
{ title: 'The Pragmatic Programmer' },
{ title: 'Agile Web Development with Rails' }
]
)
},
{
name: 'Kanagawa',
books: Book.create(
[
{ title: 'Programming Ruby' }
]
)
},
{
name: 'Chiba',
books: Book.create(
[
{ title: 'Programming Ruby' },
{ title: 'The Pragmatic Programmer' }
]
)
}
]
)
seed データの投入
DB マイグレーションを実行しデータを登録します。
bin/rails db:create db:migrate db:seed
Rails Console で確認する
rails console
で確認します。
Kanagawa Library の Book を delete_by
で削除します。
まずは、 Kanagawa
で Library を検索します。
irb(main):001:0> library = Library.find_by(name: 'Kanagawa')
Library Load (0.2ms) SELECT "libraries".* FROM "libraries" WHERE "libraries"."name" = $1 LIMIT $2 [["name", "Kanagawa"], ["LIMIT", 1]]
=> #<Library id: 2, name: "Kanagawa", created_at: "2019-08-17 00:04:21", updated_at: "2019-08-17 00:04:21">
delete_by
で title を条件に指定してデータを削除します。
irb(main):002:0> library.books.delete_by(title: 'Programming Ruby')
Book Destroy (7.4ms) DELETE FROM "books" WHERE "books"."library_id" = $1 AND "books"."title" = $2 [["library_id", 2], ["title", "Programming Ruby"]]
=> 1
delete_by
で Library も削除します。
irb(main):003:0> Library.delete_by(name: 'Kanagawa')
Library Destroy (8.1ms) DELETE FROM "libraries" WHERE "libraries"."name" = $1 [["name", "Kanagawa"]]
=> 1
Tokyo Library の Book を destroy_by
で削除します。
まずは、 Tokyo の Library を検索します。
irb(main):004:0> library = Library.find_by(name: 'Tokyo')
Library Load (0.7ms) SELECT "libraries".* FROM "libraries" WHERE "libraries"."name" = $1 LIMIT $2 [["name", "Tokyo"], ["LIMIT", 1]]
=> #<Library id: 1, name: "Tokyo", created_at: "2019-08-17 00:04:21", updated_at: "2019-08-17 00:04:21">
destroy_by
を使って Book を削除します。
irb(main):005:0> library.books.destroy_by(title: 'The Pragmatic Programmer')
Book Load (0.2ms) SELECT "books".* FROM "books" WHERE "books"."library_id" = $1 AND "books"."title" = $2 [["library_id", 1], ["title", "The Pragmatic Programmer"]]
(0.2ms) BEGIN
Book Destroy (0.3ms) DELETE FROM "books" WHERE "books"."id" = $1 [["id", 2]]
(3.3ms) COMMIT
=> [#<Book id: 2, title: "The Pragmatic Programmer", library_id: 1, created_at: "2019-08-17 00:04:21", updated_at: "2019-08-17 00:04:21">]
Library を destroy_by
で削除します。
irb(main):006:0> Library.destroy_by(name: 'Chiba')
Library Load (0.6ms) SELECT "libraries".* FROM "libraries" WHERE "libraries"."name" = $1 [["name", "Chiba"]]
(0.3ms) BEGIN
Book Load (0.6ms) SELECT "books".* FROM "books" WHERE "books"."library_id" = $1 [["library_id", 3]]
Book Destroy (0.6ms) DELETE FROM "books" WHERE "books"."id" = $1 [["id", 5]]
Book Destroy (0.5ms) DELETE FROM "books" WHERE "books"."id" = $1 [["id", 6]]
Library Destroy (0.8ms) DELETE FROM "libraries" WHERE "libraries"."id" = $1 [["id", 3]]
(7.3ms) COMMIT
=> [#<Library id: 3, name: "Chiba", created_at: "2019-08-17 00:04:21", updated_at: "2019-08-17 00:04:21">]
動作としては
delete_by(*args)
は、 where(*arg).delete_all
と
destroy_by(*arg)
は、 where(*arg).destroy_all
と
同じです。
試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try076_delete_by_destroy_by