class Fixture
attr_reader :class_name
def find_id
if @class_name.is_a?(Class)
klass = @class_name
else
klass = Object.const_get(@class_name) rescue nil
end
if klass
self[klass.primary_key]
else
# if we can't find the class just assume id
self['id']
end
end
end
def build_fixture_accessors(fixture_file, fixtures)
accessor_name = File.basename(fixture_file, '.*')
file_name = accessor_name.singularize if ActiveRecord::Base.pluralize_table_names
fixtures = fixtures.delete_if { |k, v| v.find_id.nil? }
if fixtures.empty?
""
else
<<-CODE
begin
require_dependency '#{file_name}'
rescue LoadError
# Let's hope the developer has included it himself
end
#{file_name.upcase}_MAP = {
#{fixtures.map { |k, v| ":#{k} => #{v.find_id}"}.join(",\n ")}
}
def #{accessor_name}(fixture_name)
#{fixtures.values[0].class_name}.find(#{file_name.upcase}_MAP[fixture_name])
end
CODE
end
end
class Rake::Task
def detract(prerequisite)
@prerequisites.delete(prerequisite)
end
end
FIXTURES_LAST_MOD = File.join(RAILS_ROOT, 'tmp', 'fixtures_last_modified')
desc 'sets last time fixtures were loaded'
task :touch do
FileUtils.touch(FIXTURES_LAST_MOD)
end
namespace :db do
namespace :fixtures do
desc 'checks whether fixtures were modified before loading'
task :lazy_loader do
reload_fixtures = true
if File.exists?(FIXTURES_LAST_MOD)
last_loaded_at = File.mtime(FIXTURES_LAST_MOD)
reload_fixtures = false if Dir["test/fixtures/**/*.yml"].entries.find {|f| File.mtime(f) > last_loaded_at}.nil?
end
if reload_fixtures
original_env, RAILS_ENV = RAILS_ENV, 'test' # doubt this makes a difference, but let's be safe
Rake::Task["db:fixtures:load_fixtures_and_create_accessors"].invoke
RAILS_ENV = original_env
end
end
desc "loads fixtures and creates fixture accessors file to include"
task :load_fixtures_and_create_accessors => :environment do
require 'active_record/fixtures'
fixture_accessors = []
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
fixture_files = Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*')).reject { |file| File.directory?(file) }
fixture_files.each do |fixture_file|
fixtures = Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
unless File.extname(fixture_file) == '.csv'
fixture_accessors << build_fixture_accessors(fixture_file, fixtures)
end
end
File.open(File.dirname(__FILE__) + '/../../test/fixture_accessors.rb', 'w+' ) do |file|
file.write(fixture_accessors.join("\n"))
end
end
end
end
Rake::Task['db:fixtures:load_fixtures_and_create_accessors'].enhance(['touch'])
%w(units functionals integration recent uncommitted).each do |task|
Rake::Task["test:#{task}"].detract('db:test:prepare')
Rake::Task["test:#{task}"].enhance(['environment','db:fixtures:lazy_loader'])
end