Rake задача обрезать все таблицы в Rails 3

Я хотел бы иметь задачу rake для усечения всех таблиц. Я нашел его в Интернете, но он предназначен только для Rails 2 и не работает для Rails 3 (проблема в подключении к базе данных).

rake db:reset не является вариантом, потому что я использую PostgreSQL, и он также отключает пользователя. Поэтому миграция не выполняется. Я хочу только очистить данные.

У вас, ребята, есть что-то для меня?

Я нашел это через google, а затем у меня получилось гораздо более простое решение, чем одобренное, так что вот оно: Используйте самородку database_cleaner . Вот шаги.

В вашем Gemfile (выполнить пакет после модификации):

 gem 'database_cleaner' # you might want to limit this to the dev and staging group 

С этим камнем на месте оператор DatabaseCleaner.clean_with :truncation усекает базу данных. Добавление его к задаче грабли тривиально:

 # tasks/db/clean.rake namespace :db do desc "Truncate all existing data" task :truncate => "db:load_config" do DatabaseCleaner.clean_with :truncation end end 

Вот и все. Вы также можете использовать строку DatabaseCleaner.clean_with :truncation внутри вашего файла db/seeds.rb напрямую, чтобы не забывать db/seeds.rb базу данных до посева.

Поэтому я отредактировал связанный пример с этим:

 namespace :db do desc "Truncate all existing data" task :truncate => "db:load_config" do begin config = ActiveRecord::Base.configurations[::Rails.env] ActiveRecord::Base.establish_connection case config["adapter"] when "mysql", "postgresql" ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.execute("TRUNCATE #{table}") end when "sqlite", "sqlite3" ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.execute("DELETE FROM #{table}") ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table}'") end ActiveRecord::Base.connection.execute("VACUUM") end end end end 

Этот пример основан на приведенном ниже коде Криса Леде (спасибо) и работает с Rails 3.X.

Спасибо за все советы.

По словам Криса Леде, это становится намного проще:

 ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table};") end 

Вы всегда можете перейти на версию 0, например:

 rake db:migrate VERSION=0 

Таким образом, вам даже не нужно урезать свои таблицы, и вы можете снова выполнить миграцию. Единственный улов в том, что вам нужно, чтобы ваши миграции down работали правильно.

Это решение работает в rails 3, несмотря на то, что версии основаны на методе timestamp.

Это решение показано здесь: https://stackoverflow.com/a/1196822/241367

Кроме того, вы всегда можете запустить следующее, предполагая, что ваш schema.rb обновлен:

 rake db:schema:load 

И как @kikito предлагает, вы можете запустить database_cleaner (это то, что cucumber и rspec любят использовать между тестами):

 DatabaseCleaner.clean_with :truncation 

Это позволит получить все таблицы в вашей базе данных, найти модель, связанную с этой таблицей, и вызвать # destroy_all .

 tables = ActiveRecord::Base.connection.tables tables.each do |tbl| # "users" => User tbl.classify.constantize.destroy_all end 

Ответ, заданный lzap, имеет одну конкретную проблему. Rails хочет снова запустить все миграции. Следующий код, как предложил Энтони Альберто, работает. Это дополнение проверяет таблицу schema_migrations

 namespace :db do desc "Truncate all existing data" task :truncate => "db:load_config" do begin config = ActiveRecord::Base.configurations[::Rails.env] ActiveRecord::Base.establish_connection case config["adapter"] when "mysql", "postgresql" ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.execute("TRUNCATE #{table}") if table != "schema_migrations" end when "sqlite", "sqlite3" ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.execute("DELETE FROM #{table}") if table != "schema_migrations" ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table}'") if table != "schema_migrations" end ActiveRecord::Base.connection.execute("VACUUM") end end end end