datamapper multi repository

This commit is contained in:
Jon Rowe 2010-05-30 23:10:02 +01:00
parent b0669ffcab
commit 08fe9ab136
4 changed files with 144 additions and 119 deletions

View File

@ -1,4 +1,119 @@
require 'database_cleaner/generic/base'
module DataMapper
module Adapters
class DataObjectsAdapter
def storage_names(repository = :default)
raise NotImplementedError
end
end
class MysqlAdapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
select 'SHOW TABLES'
end
def truncate_table(table_name)
execute("TRUNCATE TABLE #{quote_name(table_name)};")
end
# copied from activerecord
def disable_referential_integrity
old = select("SELECT @@FOREIGN_KEY_CHECKS;")
begin
execute("SET FOREIGN_KEY_CHECKS = 0;")
yield
ensure
execute("SET FOREIGN_KEY_CHECKS = #{old};")
end
end
end
class Sqlite3Adapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
# activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 177
sql = <<-SQL.compress_lines
SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
SQL
# activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 181
select sql
end
def truncate_table(table_name)
execute("DELETE FROM #{quote_name(table_name)};")
end
# this is a no-op copied from activerecord
# i didn't find out if/how this is possible
# activerecord also doesn't do more here
def disable_referential_integrity
yield
end
end
# FIXME
# i don't know if this works
# i basically just copied activerecord code to get a rough idea what they do.
# i don't have postgres available, so i won't be the one to write this.
# maybe codes below gets some postgres/datamapper user going, though.
class PostgresAdapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
sql = <<-SQL.compress_lines
SELECT table_name FROM "information_schema"."tables"
WHERE table_schema = current_schema()
SQL
select(sql)
end
def truncate_table(table_name)
execute("TRUNCATE TABLE #{quote_name(table_name)} CASCADE;")
end
# FIXME
# copied from activerecord
def supports_disable_referential_integrity?
version = select("SHOW server_version")[0][0].split('.')
(version[0].to_i >= 8 && version[1].to_i >= 1) ? true : false
rescue
return false
end
# FIXME
# copied unchanged from activerecord
def disable_referential_integrity(repository = :default)
if supports_disable_referential_integrity? then
execute(storage_names(repository).collect do |name|
"ALTER TABLE #{quote_name(name)} DISABLE TRIGGER ALL"
end.join(";"))
end
yield
ensure
if supports_disable_referential_integrity? then
execute(storage_names(repository).collect do |name|
"ALTER TABLE #{quote_name(name)} ENABLE TRIGGER ALL"
end.join(";"))
end
end
end
end
end
module DatabaseCleaner
module DataMapper
def self.available_strategies
@ -7,6 +122,15 @@ module DatabaseCleaner
module Base
include ::DatabaseCleaner::Generic::Base
def db=(desired_db)
@db = desired_db
end
def db
@db || :default
end
end
end
end

View File

@ -4,16 +4,18 @@ module DatabaseCleaner::DataMapper
class Transaction
include ::DatabaseCleaner::DataMapper::Base
#TODO Figure out repositories, may have to refactor connection_klass to something more sensible
def start(repo = :default)
DataMapper.repository(repo) do |r|
def start(repository = nil)
repository = self.db if repository.nil?
::DataMapper.repository(repository) do |r|
transaction = DataMapper::Transaction.new(r)
transaction.begin
r.adapter.push_transaction(transaction)
end
end
def clean(repo = :default)
DataMapper.repository(repo) do |r|
def clean(repository = nil)
repository = self.db if repository.nil?
::DataMapper.repository(repository) do |r|
adapter = r.adapter
while adapter.current_transaction
adapter.current_transaction.rollback

View File

@ -1,119 +1,7 @@
require "database_cleaner/generic/truncation"
require 'database_cleaner/data_mapper/base'
module DataMapper
module Adapters
class DataObjectsAdapter
def storage_names(repository = :default)
raise NotImplementedError
end
end
class MysqlAdapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
select 'SHOW TABLES'
end
def truncate_table(table_name)
execute("TRUNCATE TABLE #{quote_name(table_name)};")
end
# copied from activerecord
def disable_referential_integrity
old = select("SELECT @@FOREIGN_KEY_CHECKS;")
begin
execute("SET FOREIGN_KEY_CHECKS = 0;")
yield
ensure
execute("SET FOREIGN_KEY_CHECKS = #{old};")
end
end
end
class Sqlite3Adapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
# activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 177
sql = <<-SQL.compress_lines
SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
SQL
# activerecord-2.1.0/lib/active_record/connection_adapters/sqlite_adapter.rb: 181
select sql
end
def truncate_table(table_name)
execute("DELETE FROM #{quote_name(table_name)};")
end
# this is a no-op copied from activerecord
# i didn't find out if/how this is possible
# activerecord also doesn't do more here
def disable_referential_integrity
yield
end
end
# FIXME
# i don't know if this works
# i basically just copied activerecord code to get a rough idea what they do.
# i don't have postgres available, so i won't be the one to write this.
# maybe codes below gets some postgres/datamapper user going, though.
class PostgresAdapter < DataObjectsAdapter
# taken from http://github.com/godfat/dm-mapping/tree/master
def storage_names(repository = :default)
sql = <<-SQL.compress_lines
SELECT table_name FROM "information_schema"."tables"
WHERE table_schema = current_schema()
SQL
select(sql)
end
def truncate_table(table_name)
execute("TRUNCATE TABLE #{quote_name(table_name)} CASCADE;")
end
# FIXME
# copied from activerecord
def supports_disable_referential_integrity?
version = select("SHOW server_version")[0][0].split('.')
(version[0].to_i >= 8 && version[1].to_i >= 1) ? true : false
rescue
return false
end
# FIXME
# copied unchanged from activerecord
def disable_referential_integrity(repository = :default)
if supports_disable_referential_integrity? then
execute(storage_names(repository).collect do |name|
"ALTER TABLE #{quote_name(name)} DISABLE TRIGGER ALL"
end.join(";"))
end
yield
ensure
if supports_disable_referential_integrity? then
execute(storage_names(repository).collect do |name|
"ALTER TABLE #{quote_name(name)} ENABLE TRIGGER ALL"
end.join(";"))
end
end
end
end
end
module DatabaseCleaner
@ -122,10 +10,11 @@ module DatabaseCleaner
include ::DatabaseCleaner::DataMapper::Base
include ::DatabaseCleaner::Generic::Truncation
def clean(repository = :default)
def clean(repository = nil)
repository = self.db if repository.nil?
adapter = ::DataMapper.repository(repository).adapter
adapter.disable_referential_integrity do
tables_to_truncate.each do |table_name|
tables_to_truncate(repository).each do |table_name|
adapter.truncate_table table_name
end
end
@ -133,7 +22,8 @@ module DatabaseCleaner
private
def tables_to_truncate(repository = :default)
def tables_to_truncate(repository = nil)
repository = self.db if repository.nil?
(@only || ::DataMapper.repository(repository).adapter.storage_names(repository)) - @tables_to_exclude
end

View File

@ -16,6 +16,15 @@ module DatabaseCleaner
it_should_behave_like "a generic strategy"
it { should respond_to :db }
it { should respond_to :db= }
it "should store my desired db" do
subject.db = :my_db
subject.db.should == :my_db
end
it "should default to :default" do
subject.db.should == :default
end
end
end
end