はじめに
Rails 7.2 では、MariaDB で、insert_all
に returning
オプションが使えるようになりました。
MySQL では使えないので注意が必要です。
(PostgreSQL では、以前から returning
オプションが使えます。)
環境
- Ruby 3.3.2
- Rails 7.2.0.beta2
- MariaDB 11.4.2
- MySQL 8.4.0
準備
Bookモデルを作ります。
$ bin/rails g model Book title
MySQL での挙動
MySQL では returning
オプションを使うとエラーになります。
MySQL に接続するように config/database.yml
を修正して以下を実行します。
$ bin/rails db:create db:migrate
Rails コンソールで insert_all
を :returning
実行するとエラーになります。
$ bin/rails c
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
(sandbox):1:in `<main>': ActiveRecord::ConnectionAdapters::Mysql2Adapter does not support :returning (ArgumentError)
raise ArgumentError, "#{connection.class} does not support :returning"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ちなみに、returning
オプションを使わない場合は、 @rows
が []
の ActiveRecord::Result
が返ります。
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}])
Book Insert (2.7ms) INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (1, 'Programming Ruby', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) AS `books_values` ON DUPLICATE KEY UPDATE `id`=`books_values`.`id`
=>
#<ActiveRecord::Result:0x0000ffff902bf738
@column_indexes=nil,
@column_types={},
@columns=[],
@hash_rows=nil,
@rows=[]>
MariaDB での挙動
MariaDB では、returning
オプションを使うと、 ActiveRecord::Result
が返ります。
MariaDB に接続するように config/database.yml
を修正して以下を実行します。
$ bin/rails db:create db:migrate
Rails コンソールで insert_all
を :returning
オプションつきで、実行すると、 ActiveRecord::Result
が返ります。
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
Book Insert (1.0ms) INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (1, 'Programming Ruby', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) ON DUPLICATE KEY UPDATE `id`=`id` RETURNING `id`,`title`
=>
#<ActiveRecord::Result:0x0000ffff843cf468
@column_indexes=nil,
@column_types={},
@columns=["id", "title"],
@hash_rows=nil,
@rows=[[1, "Programming Ruby"]]>
ちなみに returning
オプションを省略した場合は、 id
の情報だけの ActiveRecord::Result
が返ります。
sandbox(dev)> Book.insert_all([{id: 2, title: 'Rails development'}])
Book Insert (1.1ms) INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (2, 'Rails development', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) ON DUPLICATE KEY UPDATE `id`=`id` RETURNING `id`
=>
#<ActiveRecord::Result:0x0000ffff84254340
@column_indexes=nil,
@column_types={},
@columns=["id"],
@hash_rows=nil,
@rows=[[2]]>
Rails 7.1 での挙動
Rails 7.1 では、returning
オプションを使うとエラーになります。
irb(main):001> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
(irb):1:in `<main>': ActiveRecord::ConnectionAdapters::Mysql2Adapter does not support :returning (ArgumentError)
raise ArgumentError, "#{connection.class} does not support :returning"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
まとめ
- Rails 7.2 では、MariaDB で
insert_all
にreturning
オプションが使えるようになりました。 - MySQL では使えないので注意が必要です。