All Articles

Rails allows using aliased attributes with insert_all and upsert_all

All of us would have used aliases with SQL queries as it makes the table and column names more readable. The renaming is just a temporary change and the table name does not change in the original database.

Rails now support aliased attributes with insert_all and upsert_all, which means we can add aliases in the Active Record model.

For example, here we are adding an alias name to the original title attribute of Product

  class Product < ApplicationRecord
    alias_attribute :name, :title
  end

Before

=> 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)

We can notice, it throws an error saying unknown attribute name.

After

=> 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"]]> 

Aliased attributes also work with 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]]> 

As it can be seen, it does not throw an error while using aliased attributes with insert_all and upsert_all.

Note: The enhancement is yet to be released in the official Rails version

Check out the PR for more details.