The Ruby On Rials Gudie -- Active Record Migrations

中文就是数据迁移,它是用来更改数据库的,但是它有一个挺好的设计,就是他会记录你更改的历史,你每次修改都会单独生成一个文件,然后在前一个的基础上修改。这样假如你发现了设计中的失误,那么你可以回滚到你觉得正确的版本上去。并且它的修改不是SQL级别,它是Ruby SDL级的。你的db/schema.rb反映了你的表


下面给一个小例子

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

这个就是一个migration(以后我们就用这个英文词,因为中文翻译的感觉很怪,并且你以后命令也少不了用这个词什么的,早点熟悉),它创建了一个products的表。这样就ok了

具体描述这个表原英文是这样的,很简单,就不翻译了。注意它自动生成了id这个primary key,还有因为timestaps新加了两列

This migration adds a table called products with a string column called name and a text column called description. A primary key column called id will also be added implicitly, as it's the default primary key for all Active Record models. The timestamps macro adds two columns, created_atand updated_at. These special columns are automatically managed by Active Record if they exist.


创建一个Migration


我们的migration生成的文件名字格式是这样的 YYYYMMDDHHMMSS_create_products.rb 解释下, 第一个下划线前的是UTC时间(不理解UTC没关系的,知道它是个时间戳就ok了,能够反映我们这个文件的创建的日期),第一个和第二个下划线间的是操作名(我们这里是创建,以后还可以有很多操作),第二个下划线后的是表的名字(注意,这里是复数形式,这个就体现出来了rails的命名规则的变化了,还是很有意思的,他是复数,那么就说明他是表)。


假如我们生成一个自己的Migration,其实很简单的,参考下面的命令

rails generate migration AddPartNumberToProducts

这个就ok了,他会生成一个类似的名字YYYYMMDDHHMMSS_add_part_number_to_products.rb的文件,这里进行了个命名规则的变化(其实也很简单,在rails中,model是采用驼峰式命名规则,而其余的是采用下划线的明明规则,更准确的说是只要要求大写的,是采用驼峰式命名规则的,其余的都是用下划线的),这个文件中像下面的一样

class AddPartNumberToProducts < ActiveRecord::Migration
   def change
   end
end

这是一个空的migration,我们的操作是change里面的操作,只要从里面写出来就行了。


具体几类操作:

一. create一个表


命令就是这样的

rails generate migration CreateProducts

这是最主要的命令,他会生成一个这样的文件

classCreateProducts < ActiveRecord::Migration
defchange

end

end

假如你想创建一个带有name和part_number列的表,你可以修改这个文件为下面的,就ok了,他们的属性是文本

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

很简单吧,其实还可以更简单,这样一个命令,足矣

rails generate migration CreateProducts name:string part_number:string

功效是一样的


二. 增加一个column,这个也很简单

rails generate migration AddDetailsToProducts part_number:string price:decimal

这样子他就生成了

class AddDetailsToProducts < ActiveRecord::Migration
   def change
     add_column :products , :part_number , :string
     add_column :products , :price , :decimal
   end
end
这样一个文件,就增加了两个列,当然,你也可以

rails generate migration AddDetailsToProducts

然后在修改的了

假如你想在新的列上家一个索引,那么也可以这样执行的

rails generate migration AddPartNumberToProducts part_number:string:index

这样他就增加了一个part_number的列了,并且加上了索引

生成了下面的一个文件

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


三. 删除一列

rails generate migration RemovePartNumberFromProducts part_number:string

这样就删除了part_number这个列

生成了这样文件

class RemovePartNumberFromProducts < ActiveRecord::Migration
   def change
     remove_column :products , :part_number , :string
   end
end

总结下,对于命令解释下吧(小技巧,g可以代替generate)

创建表:rails g migration CreateXXX 后面可以跟着列的名字和对应的格式

增加列:rails g migration AddXXX后面可以跟着列的名字和对应的格式加上:index的话就可以加一个索引

删除列:rails g migration RemoveXXX 后面可以跟着列的名字和对应的格式

其实区别就是第一个单词,记住一定要使用驼峰命名规则,rails讲究是约定优于规则,遵守rails的命名规则书写规则什么的,rails才会更好的和你玩


手写migration

虽然rails的migration很神奇,有人甚至说这是rails的魔法,但是我们还是要手写migration来真正明白它是做了怎么回事,我们所书写的全部是要在那个migration 的file中的change中的。


1. 先说创建表,用的函数是create_table

用法

create_table :products do |t|
   t.string :name
end

这样就创建了一个有一个类型为文本名字为name的名叫products的表,很简单。对了,他会默认的创建一个叫id的列,类型是数字类型,作为主键的。

2. 创建一个join表,就是建立两个表的级联

create_join_table:products,:categories

这样就创建了一个表叫做categories_products 假如你想自己定义名字的话就用下面的

create_join_table :products , :categories , table_name: :categorization
这样就ok了

这个表中有两列,并且非空。叫做product_id和category_id(注意是单数形式)。当然那你可以自己定义一些列的属性

这样用

create_join_table :products , :categories , column_options: {null: true }
在column_options中设定

3.修改一个表changing tables

用的方法叫change_table,他遍历整个数据,然后进行修改

change_table :products do |t|
   t.remove :description , :name #移除description 和 name 列
   t.string :part_number # 增加一个string类型叫做part_number的列
   t.index :part_number #为part_number的列加上索引
   t.rename :upccode , :upc_code #修改upccode列的名字为upc_code
end


t提供了很多方法,比如remove,index,rename。分别是移除,加上索引,重民名,而那个string是声明了一个part_number的列,具体的我从上面注释了

4. 直接执行sql

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

这里你创建的model叫product,所以你的数据库中的表是products,而这个貌似是也有点model的意思,所以大写了。所以这样就可以执行啦


总之 修改表可以使用的方法如下,只有这些方法是支持回滚的

  • 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
当我们使用migration做的事情很复杂时,我们想回滚,有些migration不知道该如何做的,我们可以用更加复杂的reversible来说明如何做

一个例子通过这个例子,我们要明白的只有两个事,up和down,up就是你执行它的时候如何办,down就是回滚时如何办

class ExampleMigration < ActiveRecord::Migration
   def change
     create_table :products do |t|
       t.references :category
     end
 
     reversible do |dir|
       dir.up do
         #add a foreign key
         execute <<- SQL
           ALTER TABLE products
             ADD CONSTRAINT fk_products_categories
             FOREIGN KEY (category_id)
             REFERENCES categories(id)
         SQL
       end
       dir.down do
         execute <<- SQL
           ALTER TABLE products
             DROP FOREIGN KEY fk_products_categories
         SQL
       end
     end
 
     add_column :users , :home_page_url , :string
     rename_column :users , :email , :email_address
   end

这个是rails 4.0 中的新写法,同样支持以前的rails的书写方法,就是吧up和down直接卸载change下面例如下个例子

class ExampleMigration < ActiveRecord::Migration
   def up
     create_table :products do |t|
       t.references :category
     end
 
     # add a foreign key
     execute <<- SQL
       ALTER TABLE products
         ADD CONSTRAINT fk_products_categories
         FOREIGN KEY (category_id)
         REFERENCES categories(id)
     SQL
 
     add_column :users , :home_page_url , :string
     rename_column :users , :email , :email_address
   end
 
   def down
     rename_column :users , :email_address , :email
     remove_column :users , :home_page_url
 
     execute <<- SQL
       ALTER TABLE products
         DROP FOREIGN KEY fk_products_categories
     SQL
 
     drop_table :products
   end
end

其实这个回滚还是有其他的写法的,但是我觉得这种就足够用了,还有一种可以用其他版本的reversible函数的方法,不过感觉很鸡肋,第一很难说能用到,第二这样开发不同版本间的依赖性太高了,不好。有兴趣可以查看下。


运行migration


用法很简单

rake db:migrate

这样将按顺序执行还没有被migrate的migration

rake db:migrate VERSION=20080906120000

这样他将执行特定时间戳的版本



回滚

rake db:rollback

回滚一步

rake db:rollback STEP=3

回滚三步



重置数据库

 rake db:reset



在特定环境中执行

rake db:migrate RAILS_ENV=test


其他的还有一些比如执行特定migration的up或者down函数啊,修改输出信息啥的。用的机会不大,不再单独写出。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值