2011-12-14 7 views
9

すべてのコントローラアクションがトランザクションで自動的にラップされ、未解決の例外が発生した場合に自動的にロールバックされるように、Railsアプリケーションを設定できますか?Rails内のすべてのコントローラアクションをラップする

私はRails 3アプリケーションで作業していますが、現在は非常に扱いにくい処理のため、多数のデータベースが変更されています。そして、私はそれを間違って、何度もやってきました!しばらくすると、データベースに一貫性のないデータが残ってしまったため、コードが機能していないことに気付きました。

私はトランザクションでこれを簡単にラップすることができます(1つが必要な明確なインスタンスです)。しかし、少なくとも開発段階では、すべてのコントローラーアクションにこのアイデアを適用することは有用であると私は考えました。

これが可能であると仮定すると、これには何か欠点がありますか?

答えて

5

できますか?多分。 すべきか?おそらくそうでなければ、これはレールの一部であるか、またはこれのために既に大きな宝石が存在するでしょう。

多くのdbアクティビティを実行している特定の複雑なコントローラアクションがあり、それらをトランザクションにしたい場合は、このビジネスロジックと永続性をモデルメソッドに入れてそこにトランザクションを配置することをお勧めします。これはまた、常にこれが起こるとは限らない場合に、より多くのコントロールを提供します。

あなたは本当に、本当に私はあなたがこのようなラックミドルウェア、(未テスト)1 https://gist.github.com/1477287でそれを行うことができるに違いないだろう、とにかくこれをしたい場合:

# make this class in lib/transactional_requests.rb, and load it on start 
require 'activerecord' 

class TransactionalRequests 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    ActiveRecord::Base.transaction do 
     @app.call(env) 
    end 
    end 
end 

# and in the app config 
config.middleware.use "TransactionalRequest" 
+0

ありがとうございました。私はこれが良いアイデアかどうかについて考えてみるつもりです。問題は、アプリケーション内で使用するトランザクションは、実際には外部トランザクションにバンドルされるということです。しかし、それを見て何らかの理由で、それは私にそれを行う方法のアイデアを与えた。コードをより読みやすくするために私のソリューションを投稿します! – asc99c

16

情報については、私はaround_filterでこれをやりました

around_filter :wrap_in_transaction 

def wrap_in_transaction 
    ActiveRecord::Base.transaction do 
    yield 
    end 
end 

これは、処理されていない例外でトランザクションをロールバックし、例外を再発生させます。

+0

私はこの考えが好きですが、これを使ってafter_commitとafter_rollbackコールバックにアクセスするにはどうしたらいいですか? – nexar

+1

スリープランドを追加することを強くお勧めします。これは、同時に多数のトランザクションがある場合に、このことがあなたのマシンを爆発させる可能性があります。 – fotanus

関連する問題