本番環境の確認用に rake db:fixtures:delete を作った

みなさんは rake db:fixtures:load を使ってますか? test/fixturesにあるテストデータを開発環境DB(正確には現在の環境のDB)に読み込むrake taskです。この操作の取り消す rake db:fixtures:delete を作りました。
http://rubyonrails.org/images/rails.png
私は、テストデータを次の目的で使っています。

  1. RSpec, Cucumber等で使うテストデータ
  2. プロトタイプとしてお客様ににデモする際のデータ
  3. 開発時のデータ

fixtures は本来 1. のテスト用のデータですが、アプリが実際に扱うデータに近いデータを準備し、お客様へのデモや日頃の開発環境用のデータとして使っています。
fixturesにデータの元があるので、思わぬバグでデータがおかしくなってしまっても再度 rake db:fixtures:load を実行すれば元に戻るので開発時も重宝します。

また、本番環境に最初にインストールする際には、RAILS_ENV=production rake db:fixtures:load を実行して、動作確認にも使えます。
しかし、本番環境にテストデータを入れておくわけには行きませんのでのテストデータを削除する必要があります。そこで rake db:fixtures:delete を作りました。

namespace :db do
  namespace :fixtures do
    desc "Delete existing fixtures from current environment's database."
    task :delete => :environment do
      require 'active_record'
      require 'active_record/fixtures'
      ActiveRecord::Base.establish_connection(Rails.env)
      
      puts "Deleting fixtures"
      Dir.glob(RAILS_ROOT + '/test/fixtures/*.yml').each do |path|
        table = File.basename(path, '.*')
        fixtures = Fixtures.new(ActiveRecord::Base.connection, table, nil, path.sub(/\.yml$/, ''))
        ids = fixtures.keys.map{|e| Fixtures.identify(e)}
        n = ActiveRecord::Base.connection.update("DELETE FROM #{table} WHERE id IN (#{ids.join(',')})")
        puts "  #{table} table #{n} records deleted"
      end
    end
  end
end

上のコードを Rakefile に追加すると rake db:fixtures:delete が使えるようになります。
このコードでは単純に全テーブルのデータを削除するのではなく fixtures にあるデータのみ削除するようにしていますので、動作確認時に本番環境で必要になるデータをアプリ上で準備(作成)できます。