Railsのtransactionを試す
準備
以下のようなUserモデルを作成します。
validatesで:name
がユニークであることを確認します。
class User < ApplicationRecord validates :name, uniqueness: true end
同名のユーザーを追加してみる
:name
がKenであるユーザーを追加します。
> User.create!(name: "Ken")
確認してみます。
>User.all.select("name") User Load (0.2ms) SELECT "users"."name" FROM "users" => [#<User:0x000055c661df3310 id: nil, name: "Ken">]
:name
がKenのユーザーが追加されました。
もう一度追加してみます。
> User.create!(name: "Ken") TRANSACTION (0.1ms) begin transaction User Exists? (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "Ken"], ["LIMIT", 1]] TRANSACTION (0.1ms) rollback transaction /usr/local/bundle/gems/activerecord-6.1.4/lib/active_record/validations.rb:80:in `raise_validation_error': Validation failed: Name has already been taken (ActiveRecord::RecordInvalid)
上のようにエラーがでて追加できませんでした。
:name
が重複するので、はじかれたのです。
もちろん、この時点で、Kenというユーザーが一人いるだけです。
>User.all.select("name") User Load (0.2ms) SELECT "users"."name" FROM "users" => [#<User:0x000055c661df3310 id: nil, name: "Ken">]
ApplicationRecord.transactionを試す
続いて、ApplicationRecord.transactionを使って、KenとBobを一気に追加してみます。
> ApplicationRecord.transaction do > User.create!(name: "Bob") > User.create!(name: "Ken") > end TRANSACTION (0.1ms) begin transaction User Exists? (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "Bob"], ["LIMIT", 1]] User Create (0.4ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Bob"], ["created_at", "2021-07-26 13:31:31.456418"], ["updated_at", "2021-07-26 13:31:31.456418"]] User Exists? (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "Ken"], ["LIMIT", 1]] TRANSACTION (0.3ms) rollback transaction /usr/local/bundle/gems/activerecord-6.1.4/lib/active_record/validations.rb:80:in `raise_validation_error': Validation failed: Name has already been taken (ActiveRecord::RecordInvalid)
Kenは既に存在するので、追加ができませんでした。
それと同時に、このトランザクションがロールバックされ、Bobの追加も取り消されました。
確認してみると、Kenしか存在しません。
>User.all.select("name") User Load (0.2ms) SELECT "users"."name" FROM "users" => [#<User:0x000055c661df3310 id: nil, name: "Ken">]
続いて、BobとJohnを追加してみます。
> ApplicationRecord.transaction do > User.create!(name: "Bob") > User.create!(name: "John") > end
これはエラーにならずに追加されます。
確認してみると、Ken,Bob,Johnの3人が存在します。
> User.all.select(:name) User Load (0.2ms) SELECT "users"."name" FROM "users" => [#<User:0x000055866e0d2330 id: nil, name: "Ken">, #<User:0x000055866e0d2268 id: nil, name: "Bob">, #<User:0x000055866e0d21a0 id: nil, name: "John">]
終わり