Skip to content

Instantly share code, notes, and snippets.

@Carmer
Last active August 31, 2016 16:48
Show Gist options
  • Save Carmer/c13c93ccbd9da189a2d55af43b22c822 to your computer and use it in GitHub Desktop.
Save Carmer/c13c93ccbd9da189a2d55af43b22c822 to your computer and use it in GitHub Desktop.

Migration with ActiveRecord and Rails

Basic CLI commands

1.) Create a new table

  • rails g migration CreateTask title:string description:text
 class AddStartDateToTask < ActiveRecord::Migration
    def change
      create_table :products do |t|
         t.string :title
         t.text :description
 
         t.timestamps
        end
    end
  end

2.) Adding or Removing columns: AddXXXToYYY attr1:type and RemoveXXXFromYYY attr1:type attr2:type

  • rails g migration AddStartDateToTask startdate:datetime

    class AddStartDateToTask < ActiveRecord::Migration
      def change
        add_column :tasks, :start_date, :datetime
      end
    end
  • rails g migration RemoveStartdateFromTask startdate:datetime

    class AddStartDateToTask < ActiveRecord::Migration
      def change
        remove_column :tasks, :start_date, :datetime
      end
    end

3.) You are not limited to one magically generated column. You can add multiple things at one time:

  • rails g migration AddDetailsToTasks attr1:type attr2:type attr3:type

        class AddStartDateToTask < ActiveRecord::Migration
          def change
            add_column :tasks, :attr1, :type
            add_column :tasks, :attr2, :type
            add_column :tasks, :attr3, :type
          end
        end

4.) You can also add a reference to a table

  • rails g migration AddReftoTasks category:references

        class AddUserRefToTasks < ActiveRecord::Migration
          def change
            add_reference :tasks, :category, index: true, foreign_key: true
          end
        end

5.) You can make a join table

  • rails g migration CreateJoinTableCustomerProduct customer product
    class CreateJoinTableCustomerProduct < ActiveRecord::Migration
      def change
        create_join_table :customers, :products do |t|
           #t.index [:customer_id, :product_id]
           #t.index [:product_id, :customer_id]
        end
      end
    end

6.) If you run an "empty" migration, rails g migration AddDetailsToProducts, Then you will get a blank migration file. "Empty" meaning you did not include any attributes to add at the end of the command.

  class AddDetailsToProducts < ActiveRecord::Migration
    def change
    end
  end

What happens when we migrate?

Each command in the migration file with execute a statement in SQL written to our database. For example:

  create_table :tasks do |t|
    t.text :title
    t.string :description
  end

will generate some SQL similar to: CREATE TABLE "tasks" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar);

If you want to see the sql written after you've migrated you can see it in the environments log file. For development it would be development.log in the log directory.

Change vs self.up and self.down

When we think about migrations, or making changes to a database, we can do and undo them. That is, if we create a table, we can drop a table. If we add a column then we can drop that column. When we use the change method for our migration, Rails is smart enough to know the inverse of the method you used to alter the structure of the database. So, if you use the add_column method, Rails know on rake db:rollback to run the remove_column method. Using the change method is the same as using self.up and add_column and having a self.down with remove column. These two migration are the same thing:

  class AddDetailsToProducts < ActiveRecord::Migration
    def change
      add_column :quantity, :integer
    end
  end

and

  class AddDetailsToProducts < ActiveRecord::Migration
    def self.up
      add_column :quantity, :integer
    end
    
    def self.down
      remove_column :quantity, :integer
    end
  end

The change method for ActiveRecord Migrations doesn't know how to do the opposite of every method. The ones it down know are the following:

  • add_column
  • add_foreign_key
  • add_index
  • add_reference
  • add_timestamps
  • change_column_default (must supply a :from and :to option)
  • change_column_null
  • create_join_table
  • create_table
  • disable_extension
  • drop_join_table
  • drop_table (must supply a block)
  • enable_extension
  • remove_column (must supply a type)
  • remove_foreign_key (must supply a second table)
  • remove_index
  • remove_reference
  • remove_timestamps
  • rename_column
  • rename_index
  • rename_table
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment