目次
fixture など テスト用のデータがコードで用意されていないプロジェクトに途中から入ったことがあります。 ここでは、そのときに Database から fixture を生成した方法について書きます。
環境
- Rails 3.1
- Ruby 1.8.7
バージョンが低いため FactoryGirl は使えません。
参考
下記のサイトを参考にしてコードを作りました。 参考にしたサイトのコードでは、 id をたよりに並び順を指定しているので、id のない scheme_migration のテーブルでエラーが発生します。 また、 DB にセッションを入れている場合は sessions テーブルも除外が必要です。 そして、モデルが存在しないテーブルも (存在の是非はともかくプロジェクト内に存在したので) 除外が必要になりました。
方法
task のコードを追加して rake db:fixtures:extract
で実行されるように ディレクトリ lib/tasks
に配置します。
コード
綺麗ではないですが 除外するテーブルをコード内で指定しています。 また、 id のないテーブルについては (主キーかあるいはどれか基準となるキーでソートすればよかったんですが) エラーが出たらエラーメッセージを出力して次に進むようになっています。
改善の余地がたくさんあるコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
def fixture_entry(table_name, obj) res = [] klass = table_name.singularize.camelize.constantize res << "#{table_name.singularize}#{obj['id']}:" klass.columns.each do |column| res << " #{column.name}: #{obj[column.name]}" end res.join("n") end namespace :db do fixtures_dir = "#{RAILS_ROOT}/tmp/fixtures/" namespace :fixtures do desc "Extract database data to the tmp/fixtures/ directory. Use FIXTURES=table_name[,table_name...] to specify table names to extract. Otherwise, all the table data will be extracted." task :extract => :environment do sql = "SELECT * FROM %s ORDER BY id" skip_tables = ["schema_migrations", "sessions"] ActiveRecord::Base.establish_connection FileUtils.mkdir_p(fixtures_dir) if ENV['FIXTURES'] table_names = ENV['FIXTURES'].split(/,/) else table_names = (ActiveRecord::Base.connection.tables - skip_tables) end table_names.each do |table_name| puts table_name begin File.open("#{fixtures_dir}#{table_name}.yml", "w") do |file| objects = ActiveRecord::Base.connection.select_all(sql % table_name) objects.each do |obj| file.write fixture_entry(table_name, obj) + "nn" end end rescue => e STDERR.puts "error: " << e.message end end end end end |