Improved extract_fixtures
I’m not sure where I originally came across the extract_fixtures rake task (maybe here)but there’s nothing better than using real data to run your Rails unit tests. Well, real in the sense that it was generated by actually using your app. But there’s a problem with extract_fixtures. Once you get some real data to base your tests on you don’t want it to change because it would break your tests. So, after the first run extract_fixtures becomes almost useless because it’ll wipe out the fixtures you’ve been working with.
So what’s a person to do? Well, in my case the answer is to beef it up a bit. The following version of extract_fixtures takes two optional parameters:
- TABLES=foos,bars,other_foos
Tables takes a comma delimited (no spaces) list of table names that you want to extract. If you pass this in it will only extract those tables. - OUTPUT_DIR=/some/fully/qualified/non-relative/path
Tell it what directory to output to.
If you improve it further please drop me a line and I’ll add or link to your enhancements here.
desc "Create YAML test fixtures from data in an existing database. " +
" Defaults to development database. Set RAILS_ENV to override. " +
"\nSet OUTPUT_DIR to specify an output directory. Defaults to test/fixtures. " +
"\nSet TABLES (a coma separated list of table names) to specify which tables to extract. " +
"Leaving it blank will extract all tables."
task :extract_fixtures => :environment do
sql = "SELECT * FROM %s"
skip_tables = ["schema_info"]
ActiveRecord::Base.establish_connection
if (not ENV['TABLES'])
tables = ActiveRecord::Base.connection.tables - skip_tables
else
tables = ENV['TABLES'].split(/, */)
end
if (not ENV['OUTPUT_DIR'])
output_dir="#{RAILS_ROOT}/test/fixtures"
else
output_dir = ENV['OUTPUT_DIR'].sub(/\/$/, '')
end
(tables).each do |table_name|
i = "000"
File.open("#{output_dir}/#{table_name}.yml", 'w') do |file|
data = ActiveRecord::Base.connection.select_all(sql % table_name)
file.write data.inject({}) { |hash, record|
hash["#{table_name}_#{i.succ!}"] = record
hash
}.to_yaml
puts "wrote #{table_name} to #{output_dir}/"
end
end
end