Migration Data Dumper Plugin
Migration Data Dumper plugin
This plugin adds two functions for use in migrations that will save and restore data for a single table into a fixture file.
save_table_to_fixturedumps data from the table into a fixture file.restore_table_from_fixturecopies the data from a fixture file into the table.
The fixtures are kept under #{RAILS_ROOT}/db/data/#{RAILS_ENV}/, and can then be version controlled (via svn, cvs, etc).
Example
Let’s say we create a posts table…
class PostsTable < ActiveRecord::Migration
def self.up
create_table "posts", :force => true do |t|
t.column "title", :string, :default => "", :null => false
t.column "text", :text, :default => "", :null => false
end
restore_table_from_fixture("posts")
end
def self.down
save_table_to_fixture("posts")
drop_table "posts"
end
end
When you migrate down (via rake migrate VERSION=0), the data for the posts table is saved in db/data/development/posts.yml, and that data is pushed back into the table when you migrate back up (via rake migrate).
Rake Tasks
(Thanks to Richard Livsey for this addition)
MMD now ships with a couple of rake tasks to manage your table fixtures outside of ruby:
rake --tasks
<snip>
rake db:restore_table_from_fixture # Restores a database table from a yaml fixture
rake db:save_table_to_fixture # Saves a database table to a yaml fixture
Cause there’s always gotta be a gotcha…
This works great until you have to edit an existing table. Consider adding a column to the posts table:
class DraftFlagForPosts < ActiveRecord::Migration
def self.up
add_column "posts", "draft", :integer, :limit => 4, :default => 1, :null => false
Post.reset_column_information
Post.find(:all).each { |p| p.draft == 0 }
restore_table_from_fixture("posts")
end
def self.down
save_table_to_fixture("posts")
remove_column "posts", "draft"
end
end
With these two migrations, if you run rake migrate VERSION=0, the following things will happen:
db/data/development/posts.ymlwill be created (by migration 002) with the latest version of the table (including the draft column).db/data/development/posts.ymlwill be recreated (by migration 001) with the latest version of the table (including the draft column).
This is an error, but doesn’t cause any real problems just yet. The problem arrises when you attempt to migrate back up (via rake migrate). The 001 migration attempts to restore the yaml file, but cannot, since the specified draft column doesn’t exist in the table.
Version to the rescue
If we add the version parameter to the calls to save_table_to_fixture and restore_table_from_fixture in the 002 migration like such:
class DraftFlagForPosts < ActiveRecord::Migration
def self.up
add_column "posts", "draft", :integer, :limit => 4, :default => 1, :null => false
Post.reset_column_information
Post.find(:all).each { |p| p.draft == 0 }
restore_table_from_fixture("posts", ".draftcol")
end
def self.down
save_table_to_fixture("posts", ".draftcol")
remove_column "posts", "draft"
end
end
Then the latter fixture is named db/data/development/posts.draftcol.yml, avoiding the whole issue.
Update
Thanks to Richard Livsey for adding the rake tasks.
Caveats
This is in use in my personal projects, but not highly tested. It is almost definitely MySQL and UNIX dependent, since I’m too lazy to change those things. Enhancements and bug fixes are very welcome.
Download
You can grab this plugin from the RubyForge account:
./script/plugin install -x svn://rubyforge.org/var/svn/mdd
Fork and edit this post on Github.
Co-Founder of