锁定老帖子 主题:Migrations流水帐
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-07-11
学习Migrations最佳的学习资料莫过于 Ruby On Rails网站上的 Guides 系统文章了,链接在 http://guides.rubyonrails.org/migrations.html 本文的很多代码都是出自那里. 在我的理解中,Migrations就是一个基于ruby,针对数据库(SQL)的DSL,它的出现也是符合Rails中处处皆Ruby的原则的,正是专注于Ruby,这样Rails才显得别样的美丽. =========================== 如何写migration ========================= 1.migration的结构 每一个migrate的类都是 ActiveRecord::Migration 的子类,每一个migrate都要重写两个方法 up 和 down: class CreateProducts < ActiveRecord::Migration def self.up #想干嘛,就干嘛 end def self.down #你后悔的时候,你会怎么做? end end 简单的说 up 方法就是操作数据库时用的,down就是你后悔了,用来回滚用的. 2.migration提供调用的方法 Migrations提供了一系列的方法来操作数据库: create_table #建表 change_table #修改表结构 drop_table #删除表 add_column #增加字段 change_column #修改字段定义 rename_column #修改字段名 remove_column #删除字段 add_index #创建索引 remove_index #删除索引 具体各个方法的详细定义,可以查看Rails的API http://api.rubyonrails.org/classes/ActiveRecord/Migration.html 这些方法替代使用SQL来操作数据库,当然也可以使用 execute 方法直接使用 SQL 来操作数据库,个人不推荐这种方式,但是在某些情况下,提供直接使用SQL也是很方便的: execute <<-SQL ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id) SQL 3.字段 定义字段有两种方法: #这个是传统的方法 create_table :products do |t| t.column :name, :string, :null => false end #这个刚出来的时候,大家都说很性感,其实不外乎就是定义一系列的快捷方法: string, # text, integer, float, decimal, datetime, timestamp, time, date, # binary, boolean . 这一系列的方法对应各种数据类型, # 还有 primary_key 方法是用来定义主键的. create_table :products do |t| t.string :name end 除了这几个经典的定义字段方法外,还有两个特别的Helper方法: #以下这个方法会自动在表中增加 created_at,updated_at这两个类型为timestamp的字段 change_table :products do |t| t.timestamps end #这个方法是定义关于关系的,但是不会为你的表加上外键约束,如果你加上约束,请另外手动添加,切记! create_table :products do |t| t.references :category # 生成 category_id #这个是关联关系中多态的定义,生成两个字段 attachment_id 和 attachment_type ,并且attachment_type的默认值为 'Photo' t.references :attachment, :polymorphic => {:default => 'Photo'} end 以上两个方法是锦上添花之作,相当的实用. 4.在migration中使用 Model 除了使用以上方法操作数据库外,其实还可以直接在migration中使用 Model 的.比如: def self.up #直接就用model来更新数据库, #你可以看到 migration 一直在提供便利让你避免使用SQL,当然不是说SQL不好,只是想让你更加的统一,只要ruby就好了. User.update_all ["receive_newsletter = ?", true] end 使用model的另外一种情况是:当前migration要删除表中的一个字段 first_name,但是你的model中的某个方法使用了这个字段作为验证,比如: class User < ActiveRecord::Base validates_presence_of :first_name end 那么当你要在migration中增加一条记录时,这个验证便不能通过,如: def self.up User.create({:name => 'name'}).save end 在这种情况下,你可以在migration中重新定义一个model: class XXXMigration < ActiveRecord::Migration class User < ActiveRecord::Base end def self.up remove_column :first_name end #这个方法的作用就是取得最新的表定义 User.reset_column_information #放心吧,这个User不会有 validates_presence_of :first_name 的验证 User.create({:name => 'name'}).save =========================== migration文件的命名 ======================= 按照Migration的约定去命名你的migration文件,会令你省不少功夫的,请千万要相信这一点. 如果migration文件名是这样的格式: AddXXXToYYY” or “RemoveXXXFromYYY XXX => 字段名, YYY => 表名. 那么migration生成的时候,Rails会自动为你加上 add_column or remove_column 比如: #留意类名 class AddPartNumberToProducts < ActiveRecord::Migration def self.up add_column :products, :part_number, :string end def self.down remove_column :products, :part_number end end class RemovePartNumberFromProducts < ActiveRecord::Migration def self.up remove_column :products, :part_number end def self.down add_column :products, :part_number, :string end end cool吧?? =========================== 如何执行migration ========================= 执行migration的经典方法: rake db:migrate #执行特定版本 rake db:migrate VERSION=20080906120000 #屏蔽migration的输出 rake db:migrate VERBOSE=false #你又后悔,可以用如下方法回滚到最近的一次migration执行的状态 rake db:rollback #回滚到最近的3次,题外话,关于这个STEP=3到底是保存在那里的,我不曾找到,在数据库的schema_migrations表中,只有版本的信息 #莫非是按schema_migrations表记录的顺序?这个还要验证一下. rake db:rollback STEP=3 =========================== 导出migration ========================= 在某些时候,你可能需要导出migration对数据库表的字义,可以导出的格式有 rb 和 sql文件两种,前一种是正宗的ruby文件,后一种是对应你使用的数据库的SQL文件. rb:大家都知道要查看某个model的属性时,只能去db/migrate中找定义文件,但是有了这个migration的定义文件后,只要打开它就能看了. sql:很多时候,程序员是没有权限操作数据库的,或者没有ruby环境,这时候导出的sql定义文件就有用了. 至于你需要那一种,可以配置一下 config/environment.rb config.active_record.schema_format => :sql # or :rb 然后执行: rake db:structure:dump 到 RAILS_ROOT/db 目录下看看吧. ================================================================== 写完了,其实这里没有多少我的东西,大部分出自 http://guides.rubyonrails.org/migrations.html ,我只不过把英文变成中文罢了. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-07-11
migration在以Oracle为数据库的时候,安全性需要慎重一下,鄙人出现过,在迁移过程中,清空的数据库的悲惨经历
|
|
返回顶楼 | |
发表时间:2009-07-12
补充一个在开发阶段很常用的命令redo:
rake db:migrate:redo rake db:migrate:redo STEP=3 |
|
返回顶楼 | |
发表时间:2009-07-12
投新手了,这帖子不应该在这里出现
|
|
返回顶楼 | |
发表时间:2009-07-12
学习了,投良好了。
|
|
返回顶楼 | |
发表时间:2009-07-12
推荐2个库一个是heroku开发的
yaml db作用是把数据导出成yml 这样就可以轻松的在sqlite mysql等多种数据库之间切换 http://github.com/search?q=yaml&type=Repositories&x=22&y=25 另一个就是生成测试数据的 http://railscasts.com/episodes/126-populating-a-database |
|
返回顶楼 | |
发表时间:2009-07-12
QuakeWang 写道 补充一个在开发阶段很常用的命令redo:
rake db:migrate:redo rake db:migrate:redo STEP=3 我没用过这几个命令,所以没写上. |
|
返回顶楼 | |
发表时间:2009-07-13
刑天战士 写道 投新手了,这帖子不应该在这里出现
呵呵... 其实就是用自己的语言翻译了一下,一来可以在自己想用的时候查一查,发出来是希望对新学习Rails的同学能有所帮助. |
|
返回顶楼 | |
发表时间:2009-07-13
我用得较多的
rake db:rollback |
|
返回顶楼 | |
发表时间:2009-07-13
一直觉得rails的guide是最好的教程,投精华了。
|
|
返回顶楼 | |