我有一个特殊的用例,我想创建一个接受块的方法,这样在该块内发生的任何事情都不会写入数据库。
显而易见的答案是使用这样的交易:
def no_db
ActiveRecord::Base.transaction do
yield
raise ActiveRecord::Rollback
end
end
但麻烦的是,如果我的no_db方法在另一个事务块中使用,那么我将在嵌套事务的情况下使用。这里的缺点是嵌套事务只有MySQL支持,我需要支持PG,但更重要的是SQLite(用于测试)。 (我知道PG是通过保存点支持的,性能有多可靠?)。
这种方法的另一个问题是它看起来效率非常低,将内容写入数据库,然后将它们回滚。如果我可以做这样的事情会更好:
def no_db_2
# ActiveRecord::Base.turn_off_database
yield
# ActiveRecord::Base.turn_on_database
end
有这样的方法吗?或者类似于我正在寻找的方法?我认为它需要相当低的水平..
(Rails版本是3.0.5,但如果有一个优雅的Rails 3.1解决方案,我会很高兴)
答案 0 :(得分:0)
这可能是一种方法:
class Book < ActiveRecord::Base
# the usual stuff
end
# Seems like a hack but you'll get the
# transaction behavior this way...
class ReadOnly < ActiveRecord::Base
establish_connection "#{Rails.env}_readonly"
end
我会认为这......
ReadOnly.transaction do
Book.delete_all
end
......应该失败。
最后,添加另一个连接到config / database.yml
development:
username: fullaccess
development_readonly:
username: readonly
一个缺点是sqlite3-ruby驱动程序中缺少对只读模式的支持。你会注意到mode参数根据文档还没有做任何事情。 http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html#M000071