现在的位置: 首页 > 综合 > 正文

rails3 数据 migration 之一 – migration 的解析

2013年10月10日 ⁄ 综合 ⁄ 共 2653字 ⁄ 字号 评论关闭

在我们深入分析migration之前,我们先看几个例子。

class CreateProducts < ActiveRecord::Migration
  def up
    create_table :products do |t|
      t.string :name
      t.text :description
 
      t.timestamps
    end
  end
 
  def down
    drop_table :products
  end
end

这个migration增加了一个products表,一个string类型的name,和一个text类型的description字段。

一个主键id 也会默认被加入,因为是默认的。所以不需要我们写出来。

Active Record里面流行的timestamp 类型的created_atupdated_at字段也会被加入。

撤销这个migration的动作非常简单,就是删除这个表。

migration不仅可以修改表的结构,你还可以用这个来修改数据库中不好的数据。

class AddReceiveNewsletterToUsers < ActiveRecord::Migration
  def up
    change_table :users do |t|
      t.boolean :receive_newsletter, :default => false
    end
    User.update_all ["receive_newsletter = ?", true]
  end
 
  def down
    remove_column :users, :receive_newsletter
  end
end

这个migration在user表中增加了一个 receive_newsletter字段,我们设置对于新的user

默认是false。但已经存在的user被认为是已经做过了。所以我们使用User模型更新数据

既有的user这个字段为true.

rails 3.1对于migration提供了一个聪明的方法叫change。这个方法可以做任何表结构的migration。

这个方法知道怎么migration和撤销操作。那样的话你不需要写一个down方法了。

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


1.1  Migrations 是类

一个migration是ActiveRecord::Migration的子类,并且实现了

2个方法up 和down.

Active Record提供了下面的方法用来做表到migration.详细到将在会后面介绍。

    add_column
    add_index
    change_column
    change_table
    create_table
    drop_table
    remove_column
    remove_index
    rename_column

如果你想对你的数据库做migration,例如创建一个外键。

然后执行任意的SQL来运行特定任务。

migration是一个普通ruby类,所以不仅限于这些功能。

例如,你可以在添加一个列之后,更新即存数据的

值。

如果一个支持事务语句数据库 (PostgreSQL or SQLite3),

migrations是被包含在事务中的。如果一个数据库不支持事务

语句(例如mysql),如果migration中的一部分运行失败,将不会

回滚,需要手动进行回滚。

1.2 在name中有什么

Migrations被存储在db/migrate文件夹下面。一个文件就是一个

Migration类。文件名到形式是:YYYYMMDDHHMMSS_create_products.rb

就是一个UTC时间加上下划线和migration的名字。

migration类的名字必须和日期之后到名字保持一致。

例如: 20080906120000_create_products.rb 类名应该是 CreateProducts

            20080906120001_add_details_to_products.rb 类名应该是 AddDetailsToProducts

如果你改了文件名,别忘记类名也要改。要不然rails会出错。

rails内部使用时间来识别他们。rails 2.1里面id是用递增数字来识别的(从1开始)。

这样的设计,在多个用户使用的时候,很明显会产生冲突。但是你也可以通过设置

返回以前rails 2.1的id生成方法。

config.active_record.timestamped_migrations = false

后来用时间来代替id的生成方法,可以解决多个用户同时使用的时候到冲突。

例如:

alice加入了2个2008090612000020080906123000的migration。

Bob加入了20080906124500,并且运行了。

Alice,发现bob更新了一个migration,他可以更新到最新。

当bob运行rake db:mgrate时候,rails会发现alice的migration没有做,

会自动做。

但有的改变无法自动识别,如果alice做了个表的删除。而bob还以为这个表还存在,

做表的migration将会出问题。

1.3 改变migration

有时候你可能在写migation的时候会犯错。如果你已经运行了到话,

只是编辑migration在重新运行一下是没用的。因为rails认为你已经

运行过了。所以你只能回滚,运行rake db:rollback。然后再运行你

修改好的migration。

如果一个很久之前的migration你想修改的话,建议是新建一个新的migration,

而不是修改旧的。这样将会产生额外的工作量。

1.4 支持的类型

Active Record支持下面的数据库类型

    :binary
    :boolean
    :date
    :datetime
    :decimal
    :float
    :integer
    :primary_key
    :string
    :text
    :time
    :timestamp

这些将会匹配到各个数据库中的各种类型。

例如在mysql中String是代表 varchar(255).

你也可以,建立字段类型不使用activerecord提供的类型。

例如:

create_table :products do |t|
  t.column :name, 'polygon', :null => false
end

不过这可能会妨碍其他数据库的移植性。

  


抱歉!评论已关闭.