Active record so sánh với application record năm 2024

Migrations are a convenient way to alter your database schema over time in a consistent way. They use a Ruby DSL so that you don't have to write SQL by hand, allowing your schema and changes to be database independent.

Show

    You can think of each migration as being a new 'version' of the database. A schema starts off with nothing in it, and each migration modifies it to add or remove tables, columns, or entries. Active Record knows how to update your schema along this timeline, bringing it from whatever point it is in the history to the latest version. Active Record will also update your

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 file to match the up-to-date structure of your database.

    Here's an example of a migration:

    class CreateProducts < ActiveRecord::Migration[7.2]
      def change
        create_table :products do |t|
          t.string :name
          t.text :description
          t.timestamps
        end
      end
    end
    

    This migration adds a table called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    0 with a string column called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    1 and a text column called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    2. A primary key column called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    3 will also be added implicitly, as it's the default primary key for all Active Record models. The

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    4 macro adds two columns,

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    5 and

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    6. These special columns are automatically managed by Active Record if they exist.

    Note that we define the change that we want to happen moving forward in time. Before this migration is run, there will be no table. After, the table will exist. Active Record knows how to reverse this migration as well: if we roll this migration back, it will remove the table.

    On databases that support transactions with statements that change the schema, each migration is wrapped in a transaction. If the database does not support this then when a migration fails the parts of it that succeeded will not be rolled back. You will have to rollback the changes that were made by hand.

    There are certain queries that can't run inside a transaction. If your adapter supports DDL transactions you can use

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    7 to disable them for a single migration.

    If you wish for a migration to do something that Active Record doesn't know how to reverse, you can use

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    8:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    This migration will change the type of the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    9 column to a string, or back to an integer when the migration is reverted. Notice the block being passed to

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    0 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    1 respectively.

    Alternatively, you can use

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 instead of

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    Migrations are stored as files in the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    5 directory, one for each migration class. The name of the file is of the form

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    6, that is to say a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration. The name of the migration class (CamelCased version) should match the latter part of the file name. For example

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    7 should define class

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    8 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    9 should define

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    0. Rails uses this timestamp to determine which migration should be run and in what order, so if you're copying a migration from another application or generate a file yourself, be aware of its position in the order.

    Of course, calculating timestamps is no fun, so Active Record provides a generator to handle making it for you:

    $ bin/rails generate migration AddPartNumberToProducts
    

    This will create an appropriately named empty migration:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    This generator can do much more than prepend a timestamp to the file name. Based on naming conventions and additional (optional) arguments it can also start fleshing out the migration.

    If the migration name is of the form "AddColumnToTable" or "RemoveColumnFromTable" and is followed by a list of column names and types then a migration containing the appropriate and statements will be created.

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    This will generate the following migration:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    If you'd like to add an index on the new column, you can do that as well.

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    This will generate the appropriate and statements:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    You are not limited to one magically generated column. For example:

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    Will generate a schema migration which adds two additional columns to the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    0 table.

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    0

    Similarly, you can generate a migration to remove a column from the command line:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    1

    This generates the appropriate statements:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    2

    If the migration name is of the form "CreateXXX" and is followed by a list of column names and types then a migration creating the table XXX with the columns listed will be generated. For example:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    3

    generates

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    4

    As always, what has been generated for you is just a starting point. You can add or remove from it as you see fit by editing the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    7 file.

    Also, the generator accepts column type as

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    8 (also available as

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    9). For example,

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    5

    generates the following call:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    6

    This migration will create a

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    1 column. are a shorthand for creating columns, indexes, foreign keys, or even polymorphic association columns.

    There is also a generator which will produce join tables if

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    2 is part of the name:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    7

    will produce the following migration:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    8

    The model, resource, and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want, then statements for adding these columns will also be created. For example, running:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    9

    This will create a migration that looks like this:

    class CreateProducts < ActiveRecord::Migration[7.2]
      def change
        create_table :products do |t|
          t.string :name
          t.text :description
          t.timestamps
        end
      end
    end
    

    You can append as many column name/type pairs as you want.

    Some commonly used can be passed directly on the command line. They are enclosed by curly braces and follow the field type:

    For instance, running:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    1

    will produce a migration that looks like this

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    2

    Have a look at the generators help output (

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    1. for further details.

    Once you have created your migration using one of the generators it's time to get to work!

    The method is one of the most fundamental, but most of the time, will be generated for you from using a model, resource, or scaffold generator. A typical use would be

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    3

    This method creates a

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    0 table with a column called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    1.

    By default,

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4 will implicitly create a primary key called

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    3 for you. You can change the name of the column with the

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    9 option, or pass an array to

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    9 for a composite primary key. If you don't want a primary key at all, you can pass the option

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    01.

    If you need to pass database-specific options you can place an SQL fragment in the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    02 option. For example:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    4

    This will append

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    03 to the SQL statement used to create the table.

    An index can be created on the columns created within the

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4 block by passing

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    05 or an options hash to the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    06 option:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    5

    Also, you can pass the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    07 option with any description for the table that will be stored in the database itself and can be viewed with database administration tools, such as MySQL Workbench or PgAdmin III. It's highly recommended to specify comments in migrations for applications with large databases as it helps people to understand the data model and generate documentation. Currently only the MySQL and PostgreSQL adapters support comments.

    The migration method creates an HABTM (has and belongs to many) join table. A typical use would be:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    6

    This migration will create a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    09 table with two columns called

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    10 and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    11.

    These columns have the option

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    12 set to

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    13 by default, meaning that you must provide a value in order to save a record to this table. This can be overridden by specifying the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    14 option:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    7

    By default, the name of the join table comes from the union of the first two arguments provided to create_join_table, in alphabetical order.

    To customize the name of the table, provide a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    15 option:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    8

    This ensure the name of the join table is

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    16 as requested.

    Also,

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    08 accepts a block, which you can use to add indices (which are not created by default) or any additional columns you so choose.

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    9

    If you want to change an existing table in place, there is .

    It is used in a similar fashion to

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4 but the object yielded inside the block has access to a number of special functions, for example:

    $ bin/rails generate migration AddPartNumberToProducts
    

    0

    This migration will remove the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    2 and

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    1 columns, create a new string column called

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    22 and adds an index on it. Finally it renames the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    23 column to

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    24.

    Similar to the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    2 and

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    1 methods we covered , Rails also provides the migration method.

    $ bin/rails generate migration AddPartNumberToProducts
    

    1

    This changes the column

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    22 on products table to be a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    29 field.

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    27 command is irreversible. You should provide your own

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    8 migration, like we discussed .

    Besides

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    27, the and methods are used specifically to change a null constraint and default values of a column.

    $ bin/rails generate migration AddPartNumberToProducts
    

    2

    This sets

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    35 field on products to a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    36 column and the default value of the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    37 field from true to false. Both of these changes will only be applied to future transactions, any existing records do not apply.

    When setting the null constraint to true, this means that column will accept a null value, otherwise the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    36 constraint is applied and a value must be passed in order to persist the record to the database.

    You could also write the above

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    34 migration as

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    40, but unlike the previous example, this would make your migration irreversible.

    Column modifiers can be applied when creating or changing a column:

    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      41 Adds a comment for the column.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      42 Specifies the collation for a

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      43 or

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      44 column.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      45 Allows to set a default value on the column. Note that if you are using a dynamic value (such as a date), the default will only be calculated the first time (i.e. on the date the migration is applied). Use

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      46 for

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      47.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      48 Sets the maximum number of characters for a

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      43 column and the maximum number of bytes for

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      50 columns.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      51 Allows or disallows

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      47 values in the column.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      53 Specifies the precision for

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      54 columns.
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      55 Specifies the scale for the

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      56 and

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def change

      reversible do |direction|  
        change_table :products do |t|  
          direction.up   { t.change :price, :string }  
          direction.down { t.change :price, :integer }  
        end  
      end  
      
      end end

      57 columns, representing the number of digits after the decimal point.

    For

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    1 or

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    27 there is no option for adding indexes. They need to be added separately using

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    4.

    Some adapters may support additional options; see the adapter specific API docs for further information.

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    51 and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    45 cannot be specified via command line when generating migrations.

    The

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    0 method allows the creation of an appropriately named column acting as the connection between one or more associations.

    $ bin/rails generate migration AddPartNumberToProducts
    

    3

    This migration will create a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    64 column in the users table. It creates an index for this column as well, unless explicitly told not to with the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    65 option.

    The method

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    66 is an alias of

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    0.

    $ bin/rails generate migration AddPartNumberToProducts
    

    4

    The polymorphic option will create two columns on the taggings table which can be used for polymorphic associations:

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    68 and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    69.

    A foreign key can be created with the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    70 option.

    $ bin/rails generate migration AddPartNumberToProducts
    

    5

    For more

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    0 options, visit the .

    References can also be removed:

    $ bin/rails generate migration AddPartNumberToProducts
    

    6

    While it's not required, you might want to add foreign key constraints to .

    $ bin/rails generate migration AddPartNumberToProducts
    

    7

    This call adds a new constraint to the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    73 table. The constraint guarantees that a row in the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    74 table exists where the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    3 column matches the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    76.

    If the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    77 column name cannot be derived from the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    78 name, you can use the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    79 option. Use the

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    9 option if the referenced primary key is not

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    81.

    For example, to add a foreign key on

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    82 referencing

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    83:

    $ bin/rails generate migration AddPartNumberToProducts
    

    8

    This will add a constraint to the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    73 table that guarantees a row in the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    74 table exists where the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    86 column matches the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    82 field.

    Several other options such as

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    1,

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    89,

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    90,

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    91, and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    92 are supported by

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    72.

    Foreign keys can also be removed using :

    $ bin/rails generate migration AddPartNumberToProducts
    

    9

    Active Record only supports single column foreign keys.

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    95 and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    96 are required to use composite foreign keys. See .

    Sometimes a single column's value isn't enough to uniquely identify every row of a table, but a combination of two or more columns does uniquely identify it. This can be the case when using a legacy database schema without a single

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    3 column as a primary key, or when altering schemas for sharding or multitenancy.

    You can create a table with a composite primary key by passing the

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    9 option to

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4 with an array value:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    0

    Tables with composite primary keys require passing array values rather than integer IDs to many methods. See also the Active Record Querying guide to learn more.

    If the helpers provided by Active Record aren't enough you can use the method to execute arbitrary SQL:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    1

    For more details and examples of individual methods, check the API documentation.

    In particular the documentation for

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    01, which provides the methods available in the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4,

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 methods.

    For methods available regarding the object yielded by

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4, see

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    06.

    And for the object yielded by

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    18, see

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    08.

    The

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 method is the primary way of writing migrations. It works for the majority of cases in which Active Record knows how to reverse a migration's actions automatically. Below are some of the actions that

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 supports:

    • (must supply

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      19 and

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      20 options)
    • (must supply

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      19 and

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      20 options)
    • (must supply

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      19 and

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      20 options)
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      30
    • (must supply table creation options and block)
    • class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      33
    • (must supply original constraint expression)
    • (must supply original type and column options)
    • (must supply original type and column options)
    • (must supply other table and original options)
    • (must supply columns and original options)
    • (must supply original options)
    • (must supply original options)

    is also reversible, as long as the block only calls reversible operations like the ones listed above.

    If you're going to need to use any other methods, you should use

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    8 or write the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 methods instead of using the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 method.

    Complex migrations may require processing that Active Record doesn't know how to reverse. You can use to specify what to do when running a migration and what else to do when reverting it. For example:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    2

    Using

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    8 will ensure that the instructions are executed in the right order too. If the previous example migration is reverted, the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 block will be run after the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    53 column is removed and before the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    54 table is dropped.

    You can also use the old style of migration using

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 and

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 methods instead of the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 method.

    The

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method should describe the transformation you'd like to make to your schema, and the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 method of your migration should revert the transformations done by the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method. In other words, the database schema should be unchanged if you do an

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 followed by a

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3.

    For example, if you create a table in the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method, you should drop it in the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 method. It is wise to perform the transformations in precisely the reverse order they were made in the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method. The example in the

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
      end
    end
    

    8 section is equivalent to:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    3

    Sometimes your migration will do something which is just plain irreversible; for example, it might destroy some data.

    In such cases, you can raise

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    69 in your

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 block.

    If someone tries to revert your migration, an error message will be displayed saying that it can't be done.

    You can use Active Record's ability to rollback migrations using the method:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    4

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    71 method also accepts a block of instructions to reverse. This could be useful to revert selected parts of previous migrations.

    For example, let's imagine that

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    73 is committed and it is later decided that a Distributors view is no longer needed.

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    5

    The same migration could also have been written without using

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    71 but this would have involved a few more steps:

    1. Reverse the order of

      $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal

      4 and

      class AddPartNumberToProducts < ActiveRecord::Migration[7.2] def change

      add_column :products, :part_number, :string  
      
      end end

      8.
    2. Replace

      $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal

      4 with

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      32.
    3. Finally, replace

      $ bin/rails generate migration AddPartNumberToProducts part_number:string:index

      2 with

      $ bin/rails generate migration AddPartNumberToProducts part_number:string:index

      3 and vice-versa.

    This is all taken care of by

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    71.

    Rails provides a set of commands to run certain sets of migrations.

    The very first migration related rails command you will use will probably be

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82. In its most basic form it just runs the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 or

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method for all the migrations that have not yet been run. If there are no such migrations, it exits. It will run these migrations in order based on the date of the migration.

    Note that running the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    85 command also invokes the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    86 command, which will update your

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 file to match the structure of your database.

    If you specify a target version, Active Record will run the required migrations (change, up, down) until it has reached the specified version. The version is the numerical prefix on the migration's filename. For example, to migrate to version 20080906120000 run:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    6

    If version 20080906120000 is greater than the current version (i.e., it is migrating upwards), this will run the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 (or

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    1. method on all migrations up to and including 20080906120000, and will not execute any later migrations. If migrating downwards, this will run the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 method on all the migrations down to, but not including, 20080906120000.

    A common task is to rollback the last migration. For example, if you made a mistake in it and wish to correct it. Rather than tracking down the version number associated with the previous migration you can run:

    This will rollback the latest migration, either by reverting the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 method or by running the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 method. If you need to undo several migrations you can provide a

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    93 parameter:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    7

    The last 3 migrations will be reverted.

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    94 command is a shortcut for doing a rollback and then migrating back up again. As with the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    95 command, you can use the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    93 parameter if you need to go more than one version back, for example:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    8

    Neither of these rails commands do anything you could not do with

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    85. They are there for convenience, since you do not need to explicitly specify the version to migrate to.

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    98 command will create the database, load the schema, and initialize it with the seed data.

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    99 command is similar to

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    98, but it operates idempotently.

    • If the database has not been created yet, the command will run as the

      class ChangeProductsPrice < ActiveRecord::Migration[7.2] def up

      change_table :products do |t|  
        t.change :price, :string  
      end  
      
      end def down
      change_table :products do |t|  
        t.change :price, :integer  
      end  
      
      end end

      98 does.
    • If the database exists but the tables have not been created, the command will load the schema, run any pending migrations, dump the updated schema, and finally load the seed data.
    • If both the database and tables exist but the seed data has not been loaded, the command will only load the seed data.
    • If the database, tables, and seed data are all in place, the command will do nothing.

    Once the database, tables, and seed data are all established, the command will not try to reload the seed data, even if the previously loaded seed data or the existing seed file have been altered or deleted. To reload the seed data, you can manually run

    $ bin/rails generate migration AddPartNumberToProducts
    

    02.

    The

    $ bin/rails generate migration AddPartNumberToProducts
    

    03 command will drop the database and set it up again. This is functionally equivalent to

    $ bin/rails generate migration AddPartNumberToProducts
    

    04.

    This is not the same as running all the migrations. It will only use the contents of the current

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 or

    $ bin/rails generate migration AddPartNumberToProducts
    

    06 file. If a migration can't be rolled back,

    $ bin/rails generate migration AddPartNumberToProducts
    

    03 may not help you. To find out more about dumping the schema see section.

    If you need to run a specific migration up or down, the

    $ bin/rails generate migration AddPartNumberToProducts
    

    08 and

    $ bin/rails generate migration AddPartNumberToProducts
    

    09 commands will do that. Just specify the appropriate version and the corresponding migration will have its

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4,

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 or

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    3 method invoked, for example:

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
      end
    end
    

    9

    By running this command the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    4 method (or the

    $ bin/rails generate migration AddPartNumberToProducts part_number:string:index
    

    2 method) will be executed for the migration with the version "20080906120000".

    First, this command will check whether the migration exists and if it has already been performed and will do nothing if so.

    If the version specified does not exist, Rails will throw an exception.

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    0

    By default running

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82 will run in the

    $ bin/rails generate migration AddPartNumberToProducts
    

    16 environment.

    To run migrations against another environment you can specify it using the

    $ bin/rails generate migration AddPartNumberToProducts
    

    17 environment variable while running the command. For example to run migrations against the

    $ bin/rails generate migration AddPartNumberToProducts
    

    18 environment you could run:

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    1

    By default migrations tell you exactly what they're doing and how long it took. A migration creating a table and adding an index might produce output like this

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    2

    Several methods are provided in migrations that allow you to control all this:

    Method Purpose Takes a block as an argument and suppresses any output generated by the block. Takes a message argument and outputs it as is. A second boolean argument can be passed to specify whether to indent or not. Outputs text along with how long it took to run its block. If the block returns an integer it assumes it is the number of rows affected.

    For example, take the following migration:

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    3

    This will generate the following output:

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    4

    If you want Active Record to not output anything, then running

    $ bin/rails generate migration AddPartNumberToProducts
    

    22 will suppress all output.

    Occasionally you will make a mistake when writing a migration. If you have already run the migration, then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82. You must rollback the migration (for example with

    $ bin/rails generate migration AddPartNumberToProducts
    

    24), edit your migration, and then run

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82 to run the corrected version.

    In general, editing existing migrations is not a good idea. You will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines.

    Instead, you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or, more generally, which has not been propagated beyond your development machine) is relatively harmless.

    The

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    71 method can be helpful when writing a new migration to undo previous migrations in whole or in part (see above).

    Migrations, mighty as they may be, are not the authoritative source for your database schema. Your database remains the source of truth.

    By default, Rails generates

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 which attempts to capture the current state of your database schema.

    It tends to be faster and less error prone to create a new instance of your application's database by loading the schema file via

    $ bin/rails generate migration AddPartNumberToProducts
    

    28 than it is to replay the entire migration history. may fail to apply correctly if those migrations use changing external dependencies or rely on application code which evolves separately from your migrations.

    Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations, but the information is nicely summed up in the schema file.

    The format of the schema dump generated by Rails is controlled by the setting defined in

    $ bin/rails generate migration AddPartNumberToProducts
    

    30. By default, the format is

    $ bin/rails generate migration AddPartNumberToProducts
    

    31, or alternatively can be set to

    $ bin/rails generate migration AddPartNumberToProducts
    

    32.

    When

    $ bin/rails generate migration AddPartNumberToProducts
    

    31 is selected, then the schema is stored in

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9. If you look at this file you'll find that it looks an awful lot like one very big migration:

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    5

    In many ways this is exactly what it is. This file is created by inspecting the database and expressing its structure using

    $ bin/rails generate migration AddDetailsToProducts part_number:string price:decimal
    

    4,

    class AddPartNumberToProducts < ActiveRecord::Migration[7.2]
      def change
        add_column :products, :part_number, :string
        add_index :products, :part_number
      end
    end
    

    4, and so on.

    However,

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 cannot express everything your database may support such as triggers, sequences, stored procedures, etc.

    While migrations may use

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    95 to create database constructs that are not supported by the Ruby migration DSL, these constructs may not be able to be reconstituted by the schema dumper.

    If you are using features like these, you should set the schema format to

    $ bin/rails generate migration AddPartNumberToProducts
    

    32 in order to get an accurate schema file that is useful to create new database instances.

    When the schema format is set to

    $ bin/rails generate migration AddPartNumberToProducts
    

    32, the database structure will be dumped using a tool specific to the database into

    $ bin/rails generate migration AddPartNumberToProducts
    

    06. For example, for PostgreSQL, the

    $ bin/rails generate migration AddPartNumberToProducts
    

    44 utility is used. For MySQL and MariaDB, this file will contain the output of

    $ bin/rails generate migration AddPartNumberToProducts
    

    45 for the various tables.

    To load the schema from

    $ bin/rails generate migration AddPartNumberToProducts
    

    06, run

    $ bin/rails generate migration AddPartNumberToProducts
    

    28. Loading this file is done by executing the SQL statements it contains. By definition, this will create a perfect copy of the database's structure.

    Because schema files are commonly used to create new databases, it is strongly recommended that you check your schema file into source control.

    Merge conflicts can occur in your schema file when two branches modify schema. To resolve these conflicts run

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82 to regenerate the schema file.

    Newly generated Rails apps will already have the migrations folder included in the git tree, so all you have to do is be sure to add any new migrations you add and commit them.

    The Active Record way claims that intelligence belongs in your models, not in the database. As such, features such as triggers or constraints, which push some of that intelligence back into the database, are not recommended.

    Validations such as

    $ bin/rails generate migration AddPartNumberToProducts
    

    49 are one way in which models can enforce data integrity. The

    $ bin/rails generate migration AddPartNumberToProducts
    

    50 option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level, these cannot guarantee referential integrity and so some people augment them with in the database.

    Although Active Record does not provide all the tools for working directly with such features, the

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def change
        reversible do |direction|
          change_table :products do |t|
            direction.up   { t.change :price, :string }
            direction.down { t.change :price, :integer }
          end
        end
      end
    end
    

    95 method can be used to execute arbitrary SQL.

    The main purpose of Rails' migration feature is to issue commands that modify the schema using a consistent process. Migrations can also be used to add or modify data. This is useful in an existing database that can't be destroyed and recreated, such as a production database.

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    6

    To add initial data after a database is created, Rails has a built-in 'seeds' feature that speeds up the process. This is especially useful when reloading the database frequently in development and test environments, or when setting up initial data for production.

    To get started with this feature, open up

    $ bin/rails generate migration AddPartNumberToProducts
    

    52 and add some Ruby code, then run

    $ bin/rails generate migration AddPartNumberToProducts
    

    02.

    The code here should be idempotent so that it can be executed at any point in every environment.

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    7

    This is generally a much cleaner way to set up the database of a blank application.

    The

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    9 or

    $ bin/rails generate migration AddPartNumberToProducts
    

    06 is a snapshot of the current state of your database and is the authoritative source for rebuilding that database. This makes it possible to delete or prune old migration files.

    When you delete migration files in the

    $ bin/rails generate migration AddPartNumberToProducts
    

    56 directory, any environment where

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    82 was run when those files still existed will hold a reference to the migration timestamp specific to them inside an internal Rails database table named

    $ bin/rails generate migration AddPartNumberToProducts
    

    58. This table is used to keep track of whether migrations have been executed in a specific environment.

    If you run the

    $ bin/rails generate migration AddPartNumberToProducts
    

    59 command, which displays the status (up or down) of each migration, you should see

    $ bin/rails generate migration AddPartNumberToProducts
    

    60 displayed next to any deleted migration file which was once executed on a specific environment but can no longer be found in the

    $ bin/rails generate migration AddPartNumberToProducts
    

    56 directory.

    There's a caveat, though with Engines. Rake tasks to install migrations from engines are idempotent, meaning they will have the same result no matter how many times they are called. Migrations present in the parent application due to a previous installation are skipped, and missing ones are copied with a new leading timestamp. If you deleted old engine migrations and ran the install task again, you'd get new files with new timestamps, and

    class ChangeProductsPrice < ActiveRecord::Migration[7.2]
      def up
        change_table :products do |t|
          t.change :price, :string
        end
      end
      def down
        change_table :products do |t|
          t.change :price, :integer
        end
      end
    end
    

    85 would attempt to run them again.

    Thus, you generally want to preserve migrations coming from engines. They have a special comment like this:

    $ bin/rails generate migration AddPartNumberToProducts part_number:string
    

    8

    Feedback

    You're encouraged to help improve the quality of this guide.

    Please contribute if you see any typos or factual errors. To get started, you can read our section.

    You may also find incomplete content or stuff that is not up to date. Please do add any missing documentation for main. Make sure to check Edge Guides first to verify if the issues are already fixed or not on the main branch. Check the Ruby on Rails Guides Guidelines for style and conventions.

    If for whatever reason you spot something to fix but cannot patch it yourself, please open an issue.

    And last but not least, any kind of discussion regarding Ruby on Rails documentation is very welcome on the official Ruby on Rails Forum.