2011-09-20 69 views
1

我有一個有點特殊的用例,我想創建一個方法來接受一個塊,這樣在塊內發生的任何事情都不會寫入到DB中。如何防止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的一流解決方案)

回答

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 

...應該失敗。

最後,添加到配置其它連接/ database.yml的

development: 
    username: fullaccess 

development_readonly: 
    username: readonly 

一個缺點是缺乏在sqlite3的,紅寶石驅動程序只讀模式支持。根據文檔,您會注意到mode參數還沒有做任何事情。 http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html#M000071

+0

謝謝!我喜歡創建一個只是指向一個虛擬DB的「ReadOnly」類的想法。這會遇到嵌套事務的問題嗎? – CambridgeMike

+0

我需要試試MySQL和PostgreSQL。直到我再次思考,這種方法才發生在我身上。我以前對系統具有相同的「只讀」訪問權限。也許這會變成寶石! –