Search code examples
ruby-on-railspostgresqlactiverecorddatabase-migrationrails-migrations

In Rails ActiveRecord Migrations, `using:` keyword


It's been decided to update certain fields from int to bigint.
Rails can't automatically reverse this kind of migration and so suggests we have to create both an up and a down action along with adding a using:.
The problem is that I honestly can't seem to find documentation on what using: does nor what the suggestion rails makes actually means (beyond what I can infer).

With that in mind, in the following example:

  • What does using: mean?
  • What does the SQL in the String used in as the value of using: mean? (I can infer but I want the actual definition)
class UpdateModelFieldType < ActiveRecord::Migration[5.2]
  def change
    reversible do |dir|
      dir.up do
        change_column :model,
                      :field,
                      :bigint,
                      using: 'field::bigint', algorithm: :concurrently

      end

      dir.down do
        change_column :model,
                      :field,
                      :int,
                      using: 'field::int',
                      algorithm: :concurrently
      end
    end
  end
end

Solution

  • Sorry, I can't find anything in the official docs about the :using option but I can tell you what it does and point you at the PostgreSQL documentation instead.

    The using: expr option adds a USING clause to the ALTER TABLE statement that gets sent to the database to change the column's type so that you get:

    alter table models alter column fields type bigint using 'field::bigint' 
    

    instead of just:

    alter table models alter column fields type bigint
    

    So what does the USING clause do? The fine manual says:

    SET DATA TYPE
    This form changes the type of a column of a table. [...] The optional USING clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. A USING clause must be provided if there is no implicit or assignment cast from old to new type.

    So the using: expr option tells the database how to convert old column values to values in the new type.

    Now what does field::bigint mean? That's a PostgreSQL-specific type cast. The standard SQL version would be cast(field as bigint).