2007-08-23

用Migration+Fixtures在数据库之间迁移数据

关键字: ruby,rails,migration,fixture
如何用migration的办法将数据在不同的rails环境数据库之间迁移?
可以用rails的migration方式,也可以用数据库自带的备份还原方式
数据库备份还原方式:
mysqldump -u user -p password dev_database > dev.sql
mysql -u user -p password produ_database < dev.sql

rails的migration方法:
将当前环境数据库所有数据dump出来,保存到test/fixtures/×yml
切换当前rails环境
在当前环境下将yaml文件加载到数据库

具体做法是给当前rails添加一个rake任务,名字是db:fixtures:dump,将rake任务代码放在lib/tasks/目录下,文件名为db_fixtures_dump.rake

ruby 代码
 
  1. namespace :db do    
  2.   namespace :fixtures do    
  3.     desc "Create YAML fixture from current database. Defaults to development database. Set RAILS_ENV to override."    
  4.     task :dump => :environment do    
  5.       sql  = "SELECT * FROM %s"    
  6.       skip_tables = ["schema_info"]    
  7.       ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)    
  8.       (ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|    
  9.         i = "000"    
  10.         File.open("#{RAILS_ROOT}/test/fixtures/#{table_name}.yml", 'w') do |file|    
  11.           data = ActiveRecord::Base.connection.select_all(sql % table_name)    
  12.           file.write data.inject({}) { |hash, record|    
  13.             hash["#{table_name}_#{i.succ!}"] = record    
  14.             hash    
  15.           }.to_yaml    
  16.         end    
  17.       end    
  18.     end    
  19.   end    
  20. end    

如果把development环境下的数据dump出来,执行
ruby 代码
 
  1. RAILS_ENV=development rake db:fixtures:dump    

如果想把fixutes文件载入到production环境,执行
ruby 代码
 
  1. RAILS_ENV=produciton rake db:fixtures:load   

这个办法可以很方便的将遗留系统中的数据库数据dump出来,然后通过migration脚本方式生产development环境数据库
首先把遗留数据库配置为rails的production环境数据库
ruby 代码
 
  1. RAILS_ENV=production rake db:schema:dump    

拿到数据库schema.rb,创建一个新的migration脚本,将schema.rb里面的内容写入migration脚本中,执行
ruby 代码
 
  1. RAILS_ENV=development rake db:migrate

产生development数据库的schema.
将production环境的数据库数据dump到test/fixtures下×.yml文件,然后复制到db/migrate目录下新建的dev_data目录下,创建一个新的migration脚本
ruby 代码
 
  1. class LoadInitializeData < ActiveRecord::Migration    
  2.   def self.up    
  3.     require 'active_record/fixtures'    
  4.     ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)    
  5.     Dir.glob(File.join(File.dirname(__FILE__),'dev_data','*.yml')).each do |fixture_file|    
  6.       Fixtures.create_fixtures(File.dirname(__FILE__)+"/dev_data"File.basename(fixture_file, '.*'))    
  7.     end    
  8.   end    
  9.    
  10.   def self.down    
  11.   end    
  12. end    

再次执行
ruby 代码
 
  1. RAILS_ENV=development rake db:migrate

这样两个脚本就可以产生一个完整可用并且跟原来遗留数据库一致的development环境数据库了.
评论
nowind 2007-10-08
load回去之后,的确还是“北京”,但就是在yaml文件中没有可读性,查看和修改都非常不方便。

真的没有解决的方法了?
lgn21st 2007-09-30
那不是乱码,就是把中文字符存为binary格式,具体原因是ruby内部处理string不是按照utf-8方式来处理的。
你可以把fixture文件load回去数据库,或者用YAML.load方法读回来,然后查看name还是“北京”

顺便不要忘记设置 $KCODE = 'u'
nowind 2007-09-29
谢谢你的文章,对我很有帮助。

但是有一个问题,就是导出来的yml文件中,数据库里的中文数据都变成了乱码了。

比如:
const_provinces_001:
name: !binary |
5YyX5Lqs

code: "11"
id: "1"
seq: "1"

本来它的name应该是"北京"的

我的数据库及所有文件都使用的是utf8编码的,怎么解决呢?
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

lgn21st
搜索本博客
存档
最新评论