Posted at

Rails6 のちょい足しな新機能を試す76(delete_by destroy_by 編)


はじめに

(多分)Rails 6 に追加された新機能を試す第76段。 今回は、 delete_by destroy_by 編です。

Rails 6 では、 ActvieRecord に delete_bydestroy_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 関係を追加します。


app/models/library.rb

class Library < ApplicationRecord

has_many :books, dependent: :destroy
end


seed データを作る

Library, Book ともに複数のデータを作成します。


db/seeds.rb

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


参考情報