我会在这里试试,因为不幸的是,DM的邮件列表似乎没有太多来自其他用户的输入。
我有理由相信这不是我们必须手动完成的事情,但也许我错了。我从我的项目中删除了ActiveRecord,并开始在DataMapper中创建模型。这一切都有效,但我想为我的模型编写单元测试(并且我的控制器功能正常)。但是,我的测试数据库在测试运行之间没有清理(很容易通过测试证明)。 AR会为您解决这个问题,但似乎DM人员在他们的dm-rails项目中没有考虑到这一点。
在绝望的尝试擦拭平板清理时,我将所有表放在我的测试数据库中。现在,由于环境是脏的,而不是我的单元测试失败,它们会因为架构不存在而失败。查看可用的rake任务,我无法在不擦除开发数据库的情况下恢复测试数据库。我开始变得疯狂,并希望DM + Rails 3的用户可以在正确的方向上轻推我。
具体来说,当我运行单元测试时,应该在测试方法之间删除所有测试数据。此外,如果我对架构进行了更改,我应该能够运行我的测试,它们应该可以工作。
我尝试将DataMapper.auto_migrate!
放入我的test_helper.rb中的setup
回调中,但这似乎没有创建架构(由于表格在尝试时不存在,测试仍然失败插入/选择记录)。
我见过https://github.com/bmabey/database_cleaner,但我们是否真的必须将一个外部库带入Rails,只是为了做一些DM可能已经拥有(看似无证)的支持?这也没有解决重新创建模式的问题。
答案 0 :(得分:1)
答案回到邮件列表上,它基本上是一个自己动手的情况,所以如果他们最终也必须这样做,为了拯救他人麻烦:
在lib / tasks下创建一个.rake文件,名为test_db_setup.rake:
require File.dirname(__FILE__) + '/../../test/database_dumper'
# Custom logic that runs before the test suite begins
# This just clones the development database schema to the test database
# Note that each test does a lightweight teardown of just truncating all tables
namespace :db do
namespace :test do
desc "Reset the test database to match the development schema"
task :prepare do
Rake::Task['db:schema:clone'].invoke
end
end
namespace :schema do
desc "Literally dump the database schema into db/schema/**/*.sql"
task :dump => :environment do
DatabaseDumper.dump_schema(:directory => "#{Rails.root}/db/schema", :env => Rails.env)
end
desc "Clones the development schema into the test database"
task :clone => [:dump, :environment] do
DatabaseDumper.import_schema(:directory => "#{Rails.root}/db/schema", :env => "test")
end
end
end
task 'test:prepare' => 'db:test:prepare'
这使用Rails提供的:test:prepare
挂钩,它在测试套件开始之前运行。它将开发数据库中的模式复制到db / schema /下的.sql文件中(每个表/视图一个),然后将这些.sql文件导入到测试数据库中。
你需要我为此编写的实用程序类(目前它是为MySQL> = 5.0.1编写的。如果你需要一个不同的数据库,你将不得不调整逻辑。
# Utility class for dumping and importing the database schema
class DatabaseDumper
def self.dump_schema(options = {})
options[:directory] ||= "#{Rails.root}/db/schema"
options[:env] ||= Rails.env
schema_dir = options[:directory]
clean_sql_directory(schema_dir)
Rails::DataMapper.configuration.repositories[options[:env]].each do |repository, config|
repository_dir = "#{schema_dir}/#{repository}"
adapter = DataMapper.setup(repository, config)
perform_schema_dump(adapter, repository_dir)
end
end
def self.import_schema(options = {})
options[:directory] ||= "#{Rails.root}/db/schema"
options[:env] ||= "test"
schema_dir = options[:directory]
Rails::DataMapper.configuration.repositories[options[:env]].each do |repository, config|
repository_dir = "#{schema_dir}/#{repository}"
adapter = DataMapper.setup(repository, config)
perform_schema_import(adapter, repository_dir)
end
end
private
def self.clean_sql_directory(path)
Dir.mkdir(path) unless Dir.exists?(path)
Dir.glob("#{path}/**/*.sql").each do |file|
File.delete(file)
end
end
def self.perform_schema_dump(adapter, path)
Dir.mkdir(path) unless Dir.exists?(path)
adapter.select("SHOW FULL TABLES").each do |row|
name = row.values.first
type = row.values.last
sql_dir = "#{path}/#{directory_name_for_table_type(type)}"
Dir.mkdir(sql_dir) unless Dir.exists?(sql_dir)
schema_info = adapter.select("SHOW CREATE TABLE #{name}").first
sql = schema_info.values.last
f = File.open("#{sql_dir}/#{name}.sql", "w+")
f << sql << "\n"
f.close
end
end
def self.directory_name_for_table_type(type)
case type
when "VIEW"
"views"
when "BASE TABLE"
"tables"
else
raise "Unknown table type #{type}"
end
end
def self.perform_schema_import(adapter, path)
tables_dir = "#{path}/tables"
views_dir = "#{path}/views"
{ "TABLE" => tables_dir, "VIEW" => views_dir }.each do |type, sql_dir|
Dir.glob("#{sql_dir}/*.sql").each do |file|
name = File.basename(file, ".sql")
drop_sql = "DROP #{type} IF EXISTS `#{name}`"
create_sql = File.open(file, "r").read
adapter.execute(drop_sql)
adapter.execute(create_sql)
end
end
end
end
这也会将.sql文件保留在架构目录中,因此如果需要引用,可以浏览它们。
现在,这只会在测试套件启动时擦除您的数据库(通过安装新的架构)。它不会在测试方法之间擦除测试。为此,您需要使用DatabaseCleaner。把它放在你的test_helper.rb中:
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation, {:except => %w(auctionindexview helpindexview)}
class ActiveSupport::TestCase
setup :setup_database
teardown :clean_database
private
def setup_database
DatabaseCleaner.start
end
def clean_database
DatabaseCleaner.clean
end
end
现在你应该好好去。当您开始运行测试时,您的架构将是新鲜的,您将在db / schema目录中获得SQL的副本,并且将在测试方法之间擦除您的数据。如果你被DatabaseCleaner的事务策略所吸引,那就是警告......这在MySQL中很少是一种安全的策略,因为MySQL表类型当前都不支持嵌套事务,所以你的应用程序逻辑可能会破坏拆解。截断仍然很快,更安全。