migration
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
migration
=========================== 如何写migration ========================= 1.migration的结构
每⼀个migrate的类都是 ActiveRecord::Migration 的⼦类,每⼀个migrate都要重写两个⽅法 up 和 down:
Ruby代码
1. class CreateProducts < ActiveRecord::Migration
2. def self.up
3. #想⼲嘛,就⼲嘛
4. end
5. def self.down
6. #你后悔的时候,你会怎么做?
7. end
8. end
简单的说 up ⽅法就是操作数据库时⽤的,down就是你后悔了,⽤来回滚⽤的.
2.migration提供调⽤的⽅法
Migrations提供了⼀系列的⽅法来操作数据库:
Ruby代码
1. create_table #建表
2. change_table #修改表结构
3. drop_table #删除表
4. add_column #增加字段
5. change_column #修改字段定义
6. rename_column #修改字段名
7. remove_column #删除字段
8. add_index #创建索引
9. remove_index #删除索引
Ruby代码
1. execute <<-SQL
2. ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categorie
s(id)
3. SQL
3.字段
定义字段有两种⽅法:
Ruby代码
1. #这个是传统的⽅法
2. create_table :products do |t|
3. t.column :name, :string, :null => false
4. end
5.
6. #这个刚出来的时候,⼤家都说很性感,其实不外乎就是定义⼀系列的快捷⽅法: string,
7. # text, integer, float, decimal, datetime, timestamp, time, date,
8. # binary, boolean . 这⼀系列的⽅法对应各种数据类型,
9. # 还有 primary_key ⽅法是⽤来定义主键的.
10. create_table :products do |t|
11. t.string :name
12. end
除了这⼏个经典的定义字段⽅法外,还有两个特别的Helper⽅法:
Ruby代码
1. #以下这个⽅法会⾃动在表中增加 created_at,updated_at这两个类型为timestamp的字段
2. change_table :products do |t|
3. t.timestamps
4. end
5.
6. #这个⽅法是定义关于关系的,但是不会为你的表加上外键约束,如果你加上约束,请另外⼿动添加,切记!
7. create_table :products do |t|
8. t.references :category# ⽣成 category_id
9.
10. #这个是关联关系中多态的定义,⽣成两个字段 attachment_id 和 attachment_type ,并且attachment_type的默认值为 'Photo'
11. t.references :attachment, :polymorphic => {:default => 'Photo'}
12. end
以上两个⽅法是锦上添花之作,相当的实⽤.
4.在migration中使⽤ Model
除了使⽤以上⽅法操作数据库外,其实还可以直接在migration中使⽤ Model 的.⽐如:
Ruby代码
1. def self.up
2. #直接就⽤model来更新数据库,
3. #你可以看到 migration ⼀直在提供便利让你避免使⽤SQL,当然不是说SQL不好,只是想让你更加的统⼀,只要ruby就好了.
4. User.update_all ["receive_newsletter = ?", true]
5. end
使⽤model的另外⼀种情况是:当前migration要删除表中的⼀个字段 first_name,但是你的model中的某个⽅法使⽤了这个字段作为验证,⽐如:
Ruby代码
1. class User < ActiveRecord::Base
2. validates_presence_of :first_name
3. end
那么当你要在migration中增加⼀条记录时,这个验证便不能通过,如:
Ruby代码
1. def self.up
2. User.create({:name => 'name'}).save
3. end
在这种情况下,你可以在migration中重新定义⼀个model:
Ruby代码
1. class XXXMigration < ActiveRecord::Migration
2. class User < ActiveRecord::Base
3. end
4. def self.up
5. remove_column :first_name
6. end
7.
8. #这个⽅法的作⽤就是取得最新的表定义
9. User.reset_column_information
10. #放⼼吧,这个User不会有 validates_presence_of :first_name 的验证
11. User.create({:name => 'name'}).save
=========================== migration⽂件的命名 ======================= 按照Migration的约定去命名你的migration⽂件,会令你省不少功夫的,请千万要相信这⼀点. 如果migration⽂件名是这样的格式: AddXXXToYYY” or “RemoveXXXFromYYY XXX => 字段名, YYY => 表名. 那么migration⽣成的时候,Rails会⾃动为你加上 add_column or remove_column ⽐如:
Ruby代码
1. #留意类名
2. class AddPartNumberToProducts < ActiveRecord::Migration
3. def self.up
4. add_column :products, :part_number, :string
5. end
6. def self.down
7. remove_column :products, :part_number
8. end
9. end
10.
11. class RemovePartNumberFromProducts < ActiveRecord::Migration
12. def self.up
13. remove_column :products, :part_number
14. end
15. def self.down
16. add_column :products, :part_number, :string
17. end
18. end
cool吧??
=========================== 如何执⾏migration ========================= 执⾏migration的经典⽅法:
Ruby代码
1. rake db:migrate
2.
3. #执⾏特定版本
4. rake db:migrate VERSION=20080906120000
1、创建数据库表格
在创建Model后,Rails ⾃动的在/db/migrate⽂件夹中⽣成了迁移编号_create_Model名.rb 格式的⽂件,如006_create_users.rb
打开该⽂件,做如下修改
class CreateUsers < ActiveRecord::Migration
def self.up
#此处加⼊要创建的表格
create_table "users" do |t|
t.column :login, :string, :null => false
t.column :email, :string
t.column :crypted_password, :string, :limit => 40 # 字符长度限制
t.column :salt, :string, :limit => 40
t.column :created_at, :datetime
t.column :updated_at, :datetime
t.column :remember_token, :string
t.column :remember_token_expires_at, :datetime
t.column :flag, :boolean, :null => false, :default => false #设置默认值
end
end
def self.down
drop_table "users"
end
end
保存后,运⾏rake db:migration
这样就可以在config/database.yml ⽂件⾥配置的数据库中创建⼀个名为:users的数据库表,并且拥有相应的表字段。
2、修改数据库表格
如果需要修改之前已经创建好的数据库表,很多⼈习惯知道⽤GUI⼯具到数据库中直接做删除数据表、增加数据表字段、删除数据表字段以及修改⼀些字段的属性设置。
当然这样做的效果是⼀样的,但是假如有那么⼀天我们所编写的程序因为之前对数据库进⾏了修改⽽产⽣了严重的BUG,我们必须将它修改回来,但是我们现在⼜忘记了原来的数据表的设置,那么这样就⿇烦了。
但是如果我们能够记录我们对数据库这⾥做⼀个例⼦了说明:
(1)、删除数据库表,并重建⼀个新的数据库表
class ChangeAttachment < ActiveRecord::Migration
def self.up
drop_table :attachments # 删除数据库表
create_table :attachments do |t|
t.column "owner_id", :integer, :null => false
t.column "owner_model", :string, :default => "", :null => false
t.column "type", :string, :default => "", :null => false
t.column "filepath", :string, :default => "", :null => false
t.column "filename", :string, :default => "", :null => false
t.column "type_flag", :string
t.column "enable", :boolean, :default => true, :null => false
end
end
def self.down
end
end
(2)、增加索引
class AddColumnAndIndex < ActiveRecord::Migration
def self.up
add_index :systems,:client_id
add_index :systems,:scale_length
add_index :systems,:development_start_on
end
def self.down
remove_index :systems,:client_id
remove_index :systems,:scale_length
remove_index :systems,:development_start_on
end
end
(3)、增加数据表字段
class AddColumnToHolidayrecord < ActiveRecord::Migration
def self.up
add_column :holiday_records, :revert_flag, :boolean, :null => false, :default => false
end
def self.down
remove_column :holiday_records, :revert_flag
end
end
(4)、修改字段属性
class ChangeUserColumns < ActiveRecord::Migration
def self.up
change_column :users, :birthday, :date
change_column :users, :graduated_at, :date
change_column :users, :dimission_at, :date
end
def self.down
change_column :users, :birthday, :datetime
change_column :users, :graduated_at, :datetime
change_column :users, :dimission_at, :datetime
end
end
注意在上⾯例⼦中的关键字如:create_table,drop_table,add_index等等,这些⽅法决定了数据迁移将进⾏何种操作。
3、数据预先导⼊数据库
有些数据在项⽬移交后需要在数据库中⽣成基本⼀些数据,⽐如说⼀些地名,⼀些不变的数据,还有⼀些项⽬的初始数据。
因为作为开发⼈员项⽬移交后我们不能把⾃⼰的数据库给⽤户,只能是⽤户创建好数据库后⽤数据迁移创建所需的数据表。
但是那时数据库中没有任何数据,所以可以⽤数据迁移将我们所要的数据加⼊到数据库当中。
⽐如下⾯的例⼦。
#初始数据
class CreateStateDatas < ActiveRecord::Migration
def self.up
State.create(:name=>'北海道')
State.create(:name=>'青森県')
State.create(:name=>'岩⼿県')
State.create(:name=>'宮城県')
State.create(:name=>'秋⽥県')
State.create(:name=>'⼭形県')
State.create(:name=>'福島県')
State.create(:name=>'茨城県')
State.create(:name=>'栃⽊県')
end
def self.down
end
end
#批量修改数据
class ChangeUserNameFulltext < ActiveRecord::Migration
def self.up
users = User.find(:all)
for user in users
unless user.valid?
= "ユーザ名全⾓⽂字"
user.save!
end
end
end
def self.down
end
end
4、处理⼀些与数据库⽆关的操作
migration不仅仅可以做与数据库有关的各种操作,同样可以做些其他的操作,只是我们习惯⽤数据迁移来对数据库版本进⾏控制。
这个⽅法我们不常⽤,如果需要⽤到我们可以写到self.up当中,⽽在self.down中写⼀个相反的操作代码。
5、migration的⼯作原理
有些⼈可能对migration的⼯作原理不了解。
这⾥我简单的说明⼀下。
每个迁移任务都有⾃⼰的编号,编号从1开始,后续的每个新的任务都会得到在原基础上加1的编号。
Rails会记住最近⼀次作于数据库的迁移任务编号,登记到/db/schema.rb中
当你要求使⽤新的迁移任务来更新数据库结构,它会将所有可⽤的迁移编号与当前的数据库结构编号进⾏⽐较。
只要找到编号⽐Rails所登记的最⼤编号还⼤的迁移任务,
rake将运⾏该任务。
这⾥要注意的是Rails只关注编号,⽽不关注你给迁移任务所取的任务名。
(1)、创建和运⾏迁移任务
命令:rake db:migration
(2)、回退到某个迁移任务版本
命令:rake db:migration version=10 这⾥是将迁移任务的版本回到10,注意version、= 、数字之间没有空格
(3)、解析迁移任务
每个迁移任务中都有up⽅法和down⽅法,如下
class ChangeUserNameFulltext < ActiveRecord::Migration
def self.up
end
def self.down
end
end
其中up()⽅法负责修改数据库,down()负责撤销这些修改,对应的编号管理中up()⽅法是从⼩到⼤的顺序执⾏,⽽down()则是由⼤到⼩的顺序执⾏。