Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7: insert_allとupsert_allで属性のエイリアスを指定可能になる(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

参考: 週刊Railsウォッチ20220516 insert_allupsert_allalias_attributesもサポート

#45036は、現時点ではmainブランチにのみマージされています。

Rails 7: insert_allとupsert_allで属性のエイリアスを指定可能になる(翻訳)

SQLクエリでエイリアスを使ってテーブル名やカラム名を読みやすくするのは誰もがやったことがあるでしょう。このリネームは一時的な変更であり、元のデータベースのテーブル名は変更されません。

Railsでinsert_allや upsert_allで属性のエイリアスがサポートされ、alias_attributeでActive Recordモデルに追加したエイリアス属性を使えるようになりました。

たとえば、以下のProductモデルにtitle属性のエイリアスとしてnameを追加したとしましょう。

  class Product < ApplicationRecord
    alias_attribute :name, :title
  end

改修前

#=> Product.insert_all [{ name: "Detergent", description: "A mixture of surfactants with cleansing properties" }], returning: :name

#=> /Users/murtazabagwala/.rvm/gems/ruby-3.0.2/gems/activerecord-7.0.3/lib/active_record/insert_all.rb:264:in `extract_types_from_columns_on': unknown attribute 'name' for Product. (ActiveModel::UnknownAttributeError)

ご覧のように、未知のname属性があるというエラーが発生します。

改修後

#=> Product.insert_all [{ name: "Detergent", description: "A mixture of surfactants with cleansing properties" }], returning: :name

Product Insert (2.2ms)  INSERT INTO "products" ("title","description","created_at","updated_at") VALUES ('Detergent', 'A mixture of surfactants with cleansing properties', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) ON CONFLICT  DO NOTHING RETURNING "title" AS "name"

#=> #<ActiveRecord::Result:0x00007f921ae855e0 @column_types={}, @columns=["name"], @hash_rows=nil, @rows=[["Detergent"]]>

upsert_allで属性のエイリアスを使えるようになりました。

#=> Product.upsert_all [{ id: 1, name: "Soap"}]

Product Upsert (4.7ms)  INSERT INTO "products" ("id","title","created_at","updated_at") VALUES (1, 'Soap', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) ON CONFLICT ("id") DO UPDATE SET updated_at=(CASE WHEN ("products"."title" IS NOT DISTINCT FROM excluded."title") THEN "products".updated_at ELSE CURRENT_TIMESTAMP END),"title"=excluded."title" RETURNING "id"
# => #<ActiveRecord::Result:0x00007f92185c5650 @column_types={}, @columns=["id"], @hash_rows=nil, @rows=[[1]]>

ご覧のように、insert_allupsert_allで属性のエイリアスを使ってもエラーが発生しなくなりました。

原注: この改良は、公式バージョンのRailsではまだリリースされていません。

詳しくは#45036を参照してください。

関連記事

Railsエンジンは使いすぎに注意(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。