如何防止ActiveRecord写入数据库?

时间:2011-09-20 21:38:17

标签: ruby-on-rails ruby-on-rails-3 activerecord

我有一个特殊的用例,我想创建一个接受块的方法,这样在该块内发生的任何事情都不会写入数据库。

显而易见的答案是使用这样的交易:

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解决方案,我会很高兴)

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