require 'yaml' discard_old = ENV["DISCARD"] desc 'Create YAML test fixtures from data in an existing database. Defaults to development database. Set RAILS_ENV to override. Use args table and limit to dump one table and limit number of records' task :extract_fixtures, [:table, :limit, :conditions ]=> :environment do |t, args| class Hash # Replacing the to_yaml function so it'll serialize hashes sorted their keys) # # Original function is in /usr/lib/ruby/1.8/yaml/rubytypes.rb def to_yaml( opts = {} ) YAML::quick_emit( object_id, opts ) do |out| out.map( taguri, to_yaml_style ) do |map| sort.each do |k, v| # <-- here's my addition (the 'sort') map.add( k, v ) end end end end end args.with_defaults(:table => nil, :limit => nil, :conditions => nil ) limit = args.limit.nil? ? "" : "LIMIT #{args.limit}" cond = args.conditions.nil? ? "" : "WHERE #{args.conditions}" sql = "SELECT * FROM %s #{cond} #{limit}" skip_tables = ["schema_info" ] if args.table.nil? tables = ActiveRecord::Base.connection.tables - skip_tables else tables = [ "#{args.table}"] end ActiveRecord::Base.establish_connection tables.each do |table_name| path = "#{RAILS_ROOT}/test/fixtures/#{table_name}.yml" old_fixtures = YAML.load_file(path) File.open( path, 'w' ) do |file| data = ActiveRecord::Base.connection.select_all(sql % table_name) data << old_fixtures.keys.collect {|f| old_fixtures[f]["fixtures_old_key_value"] = f old_fixtures[f] } unless !discard_old.blank? || !old_fixtures data.flatten! file.write data.inject({}) { |hash, record| if record.has_key?("fixtures_old_key_value") key = record.delete "fixtures_old_key_value" hash[ key ] = record else hash["#{table_name}_#{record["id"]}" ] = record end hash }.to_yaml end end end