我们正在尝试为一组使用与ActiveRecord :: Base不同的数据库连接的模型加载fixture(在本例中继承自Foo :: Base)。
我们创建了这个模块,我们将其包含在ActiveSupport :: TestCase中,并指定.yml文件的路径,例如foo_fitures :all
。这适用于第一次运行的测试。定义了夹具访问器,并在数据库中找到记录。但是对于后续测试,数据库中没有记录。
module Foo::Fixtures
extend ActiveSupport::Concern
included do
setup :setup_foo_fixtures
teardown :teardown_foo_fixtures
class_attribute :foo_fixture_path
class_attribute :foo_fixture_table_names
self.foo_fixture_table_names = []
end
module ClassMethods
def foo_fixtures(*fixture_names)
if fixture_names.first == :all
fixture_names = Dir[foo_fixture_path.join("**/*.yml")].map { |f| File.basename(f, ".yml") }
else
fixture_names = fixture_names.flatten.map { |n| n.to_s }
end
self.foo_fixture_table_names |= fixture_names
require_fixture_classes(fixture_names)
setup_fixture_accessors(fixture_names)
end
end
def setup_foo_fixtures
@loaded_fixtures.merge!(load_foo_fixtures)
end
def teardown_foo_fixtures
Foo::Base.clear_active_connections!
end
private
def load_foo_fixtures
foo_classes = Foo::Base.subclasses.flat_map { |klass| klass.abstract_class ? klass.subclasses : klass }
class_names = foo_classes.each_with_object({}) do |klass, memo|
memo[klass.table_name.to_sym] = klass if klass.table_name.present? && foo_fixture_table_names.include?(klass.table_name)
end
foo_fixtures = ActiveRecord::Fixtures.create_fixtures(foo_fixture_path, foo_fixture_table_names, class_names) do
Foo::Base.connection
end
Hash[foo_fixtures.map { |f| [f.name, f] }]
end
end
Rails的夹具系统有点复杂,我无法弄清楚我们缺少什么来确保我们的额外灯具已经加载。
答案 0 :(得分:0)
行。看起来它可能是从数据库中删除我们的灯具的事务。我的猜测是,在我们的代码加载到灯具之前,事务已经开始了,所以这就是为什么他们在那里进行第一次测试,但是在第二次测试中出现了。
所以我们改变了策略,现在我们只是挂钩load_fixtures
和fixtures
。这很好用。
module FooFixtures
module ClassMethods
def foo_fixture_classes
collect_subclasses = ->(k) { k.abstract_class ? k.subclasses.flat_map(&collect_subclasses) : k }
Foo::Base.subclasses.flat_map(&collect_subclasses)
end
def foo_fixture_path
Rails.root.join("test/foo_fixtures")
end
def foo_fixture_table_names
Dir[foo_fixture_path.join("**/*.yml")].map { |f| File.basename(f, ".yml") }
end
def fixtures(*fixture_names)
super
if fixture_names.first == :all
require_fixture_classes(foo_fixture_table_names)
setup_fixture_accessors(foo_fixture_table_names)
end
end
end
private
def load_fixtures
foo_fixture_path = self.class.foo_fixture_path
foo_fixture_table_names = self.class.foo_fixture_table_names
class_names = self.class.foo_fixture_classes.each_with_object({}) do |klass, memo|
memo[klass.table_name.to_sym] = klass if klass.table_name.present? && foo_fixture_table_names.include?(klass.table_name)
end
foo_fixtures = ActiveRecord::Fixtures.create_fixtures(foo_fixture_path, foo_fixture_table_names, class_names) do
Foo::Base.connection
end
super.merge(Hash[foo_fixtures.map { |f| [f.name, f] }])
end
end
class ActiveSupport::TestCase
extend FooFixtures::ClassMethods
prepend FooFixtures
self.foo_fixture_classes.each do |fixture_class|
set_fixture_class fixture_class.table_name.to_sym => fixture_class
end
...
end