establish_connectionを使い複数DBに接続しているRailsアプリで、transactionをかけようとしてハマった。
establish_connectionを使って複数DBを扱っている時は、対象となるオブジェクトのデータがあるDBとコネクションのあるクラス(インスタンス)をレシーバに指定しないとロールバックが効かない。
問題が起きたケースでは以下のように、基本的にmodelのデータを別DBと連携するように設定している。
class Examples < ApplicationRecord
#このクラスを継承したモデルでは別DBのデータを使う。
self.abstract_class = true
establish_connection "example_db_2_#{Rails.env}".to_sym
end
class Example1 < Example
...
end
class Example2 < Example
...
end
この書き方ではロールバックが効かないので注意が必要。
ActiveRecord::Base.transaction do
example1 = Example1.new
example1.save!
...
example2.save!
end
↓こちらが正解
Example.transaction do
example1 = Example1.new
example1.save!
...
example2.save!
end
上に書いたとおり、レシーバーにトランザクション対象のオブジェクトのDBとコネクションのあるクラス(インスタンス)を指定する必要がある。
ちなみに、そのモデルクラスがどのDBとコネクションがあるのかは以下のメソッドで確認出来る。
クラス名.connection