Rails Database Migrations 3 Writing a Migration 编写数据迁移

阅读更多

version: rails 4.1

3 编写数据迁移

一旦你已经创建了你的 migration,使用的是生成器中的一个,现在是时候让它工作了!

3.1 Creating a Table 创建表

 

create_table 方法是最基本方法之一,但大多数时候,使用一个 model 或者 scaffold 生成器来为你生成数据表。基本的用法如下:

create_table :productsdo|t|

  t.string :name

end

这创建了一个 products 数据表,有一个数据列名为 name (下面将会讨论这个,一个隐式的数据列)。

默认的情况下,create_table 将会创建一个主键叫做 id。你能够改变主键的名称,用 :primary_key 属性(不要忘了更新相对应的model)或者你根本不需要一个主键,你能够传入一个属性 id: false。如果你需要传入数据库的详细属性,你可以代入一个SQL块在 :options 属性。例如:

create_table :products, options: "ENGINE=BLACKHOLE"do|t|

  t.string :name, null: false

end

将会把 ENGINE=BLACKHOLE 添加到SQL语句,用来创建数据表(当使用MYSQL时候,默认的 ENGINE=InnoDB)。

3.2 Creating a Join Table 创建一个关联表

migration 方法 create_join_table 创建了一个 HABTM 关联表。通常的用法:

create_join_table :products, :categories

创建了一个 categories_products 数据表,有两个列,名字是 category_id 和 product_id。这些列有属性 :null,默认设置false。这个能够被重写,通过声明 :column_options 属性。

create_join_table :products, :categories, column_options: {null: true}

将会创建 product_id 和 category_id 其属性 :null 为 true。

你可以通过传入属性 :table_name,当你想要定制数据表名的时候。例如:

create_join_table :products, :categories, table_name: :categorization

将会创建一个名为 categoriztion 的数据表。

create_join_table 也可以接受一段代码块,你可以用来增加索引(默认不会创建索引)或者额外的列:

create_join_table :products, :categoriesdo|t|

  t.index :product_id

  t.index :category_id

end

3.3 Changing Tables 更改表

create_table 的类似方法是 chang_table,用来更改已存在的数据表。它的用法和 create_table 非常的相似,对于代码块中产生对象有着更多的设置技巧。例如:

change_table :productsdo|t|

  t.remove :description, :name

  t.string :part_number

  t.index :part_number

  t.rename :upccode, :upc_code

end

移除了 description 和 name 的列,创建了一个 part_number string的列,以及增加了一个索引。最后它重命名了 upccode 列。

3.4 When Helpers aren't Enough 当缺少Helper的时候

如果由 Active Record 提供的 helpers 缺少时,你可以使用 execute 方法来生成任意的SQL:

Product.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')

可以看到更多的细节和各个方法的例子,浏览API文档。尤其在这个文档中 ActiveRecord::ConnectionAdapters::SchemaStatements (提供了在change中可用的方法,up 和 down 方法),ActiveRecord::ConnectionAdapters::TableDefinition (通过 create_table 提供在对象生成中的可用方法),ActiveRecord::ConnectionAdapters::Table  (通过 change_table 提供在对象生成中的可用方法)。

 

3.5 Using the change Method 使用改变方法

 

change 方法是编辑 migrations 的主要方式。它能搞定大部分的情况,Active Record 知道如何去 自动地回滚 migration。一般地,change 方法仅仅提供了这些 migration 定义:

  • add_column
  • add_index
  • add_reference
  • add_timestamps
  • create_table
  • create_join_table
  • drop_table (must supply a block)
  • drop_join_table (must supply a block)
  • remove_timestamps
  • rename_column
  • rename_index
  • remove_reference
  • rename_table

change_table 同样也是可逆的,只要代码块没有调用 change,change_default 或者 remove。

 

如果你打算需要使用其他的方法,你应该使用 reversible 或者编写 up 和 down 方法来取代 change 方法。

 

3.6 Using reversible 使用回滚

复杂的 migrations 可能需要处理,Active Record 不知道如何去回滚。你能够使用 reversible 去指出 当运行一个 migration 时能做什么,当回滚时还能做其他的什么。例如:

classExampleMigration < ActiveRecord::Migration

  defchange

    create_table :productsdo|t|

      t.references :category

    end

 

    reversible do|dir|

      dir.up do

        #add a foreign key

        execute <<-SQL

          ALTERTABLEproducts

            ADDCONSTRAINTfk_products_categories

            FOREIGNKEY(category_id)

            REFERENCEScategories(id)

        SQL

      end

      dir.down do

        execute <<-SQL

          ALTERTABLEproducts

            DROPFOREIGNKEYfk_products_categories

        SQL

      end

    end

 

    add_column :users, :home_page_url, :string

    rename_column :users, :email, :email_address

  end

end

使用 reversible 将会确保,命令被执行到右边的顺序列表中。如果先前的migration例子被回滚了, down 代码块将会在 home_page_url 列被删除之后和products数据表被删除之前运行。

有的时候,你的 migration 将会做一些不可逆的操作;例如,可能要销毁一些数据。在这样的例子中,在你的down代码块中,你能够抛出 ActiveRecord::IrreversibleMigration。如果有些人尝试恢复你的 migration, 一个错误信息将被显示出来,提示这是不能够做的。

3.7 Using the up/down Methods 使用up/down方法

你也能够使用migration的旧类型,通过使用 up 和 down 方法替代 change 方法。up 方法应该描述了转换,你可以制定你的数据库模式,你的 migration 的 down 方法应该可以回滚up方法做的转换。也就是说,数据库模式应该是未改变的,如果你执行了up之后就执行down。例如,如果你在 up 方法中创建了一个数据表,你在 down 方法中应该删除它。在确切地回滚顺序中,他们被创建于 up 方法里,这是很明智地回滚转化过程。在可逆的部分例子是类似于:

classExampleMigration < ActiveRecord::Migration

  defup

    create_table :productsdo|t|

      t.references :category

    end

 

    # add a foreign key

    execute <<-SQL

      ALTERTABLEproducts

        ADDCONSTRAINTfk_products_categories

        FOREIGNKEY(category_id)

        REFERENCEScategories(id)

    SQL

 

    add_column :users, :home_page_url, :string

    rename_column :users, :email, :email_address

  end

 

  defdown

    rename_column :users, :email_address, :email

    remove_column :users, :home_page_url

 

    execute <<-SQL

      ALTERTABLEproducts

        DROPFOREIGNKEYfk_products_categories

    SQL

 

    drop_table :products

  end

end

如果你的 migration 是不可逆的,你应该从 down 方法中抛出 ActiveRecord::IrreversibleMigration。如果有人想要尝试恢复你的 migration,一个错误的信息将被显示出来,提示他不能够被这样做。

 

3.8 Reverting Previous Migrations 恢复先前的migrations

你能够使用 Active Record 的能力来回滚 migrations,通过使用 revert 方法:

require_relative '2012121212_example_migration'

 

classFixupExampleMigration < ActiveRecord::Migration

  defchange

    revert ExampleMigration

 

    create_table(:apples) do|t|

      t.string :variety

    end

  end

end

revert 方法也接受一系列的指令用来恢复。这变得很有用,用于恢复被选中的一些先前的 migrations。例如,让我们来想象一下,ExampleMigration 被提交了,最好是能找到替代的来序列化产品列表,这可以稍后来决定。可以这样写:

classSerializeProductListMigration < ActiveRecord::Migration

  defchange

    add_column :categories, :product_list

 

    reversible do|dir|

      dir.up do

        # transfer data from Products to Category#product_list

      end

      dir.down do

        # create Products from Category#product_list

      end

    end

 

    revert do

      # copy-pasted code from ExampleMigration

      create_table :productsdo|t|

        t.references :category

      end

 

      reversible do|dir|

        dir.up do

          #add a foreign key

          execute <<-SQL

            ALTERTABLEproducts

              ADDCONSTRAINTfk_products_categories

              FOREIGNKEY(category_id)

              REFERENCEScategories(id)

          SQL

        end

        dir.down do

          execute <<-SQL

            ALTERTABLEproducts

              DROPFOREIGNKEYfk_products_categories

          SQL

        end

      end

 

      # The rest of the migration was ok

    end

  end

end

同样的 migration 能够不使用 revert 来编写,但这将会涉及到更多的一些细节:恢复的顺序,create_table 和 reversible,用 drop_table 来替代 create_table,最终用 down 来替代 up 反之亦然。这些都是 revert 所需要注意的。

 

original url: http://guides.rubyonrails.org/migrations.html#writing-a-migration

你可能感兴趣的:(ruby,rails,migration)