ActiveRecord 3.1.0多个数据库

时间:2011-09-12 15:54:48

标签: ruby activerecord

我正在尝试将ActiveRecord gem升级到最新的3.1.0版本并看到引发了很多异常,我认为这是由于我们如何处理多个数据库。

对于我们的每个数据库,我们指定一个单独的基类,它继承自ActiveRecord::Base,并在那里调用establish_connection。没有跨数据库关系。到目前为止,这对我们来说还不错。

升级到ActiveRecord 3.1.0后,我看到它在遍历关系时失败并出现ActiveRecord::ConnectionNotEstablished异常(即它会成功从数据库中提取单个实体或一组实体,但在导航时失败到相关的课程。)

回溯的顶线是C:/Ruby/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_pool.rb:410:in 'retrieve_connection',所以我稍微挖了一下。该方法定义如下:

def retrieve_connection(klass) #:nodoc:
    pool = retrieve_connection_pool(klass)
    (pool && pool.connection) or raise ConnectionNotEstablished
end

我的简单测试(puts Customer.first.address)调用retrieve_connection 3次。使用Customer作为klass参数两次,使用ActiveRecord::Base作为参数一次 - 这是因为establish_connection没有为ActiveRecord::Base调用失败。

实际问题然后 - 是否有一种新的推荐方法来处理ActiveRecord中的多个数据库连接?如果是这样,它是什么?

如果没有,可能导致此问题的原因是什么?

2 个答案:

答案 0 :(得分:9)

昨天我在升级到ActiveRecord 3.1.0时遇到了同样的问题。我不能说在ActiveRecord 3.1中是否有一种新的推荐方法来处理多个数据库连接,但我确实找到了解锁自己的方法。

现在必须在ActiveRecord :: Base上建立连接,以便确定适配器的表名长度/规则。除了在我的数据库初始化程序中建立的其余连接外,我现在还为我的一个数据库建立了一个ActiveRecord :: Base连接(无论哪个连接都没关系。)

我想有一个更好的解决方案可以找到,但我现在很高兴能够畅通无阻。

答案 1 :(得分:3)

我正在使用这个解决方案 - 我看到的是当在每个OtherDb类中调用establish_connection时 - 似乎有很多开销重新加载表定义,每次重新加载类def时我都会随机查看问题。

# The idea here is to specify that a given model should use another
# database without having to change the entire inheritance hierarchy

# declare model for table in primary connection
class Bar < ActiveRecord::Base
  # assume we have logic here that we don't want to refactor into a module
  # but we do want to inherit in OtherDb::Bar
end

module Foo

  # base model in Foo namespace - uses another db
  class BaseConnection < ActiveRecord::Base
    # OtherDb::Title.database contains a db config hash
    # This would probably go in the initializers
    establish_connection OtherDb::Title.database 
  end

  # module used to override db connection
  module OtherDb::Base
    def retrieve_connection
      # connection_handler.retrieve_connection(self) #  normal behavior
      connection_handler.retrieve_connection(Foo::BaseConnection) # use db from Foo::BaseConnection
    end
  end

  # Foo::Bar is identical to ::Bar but is in another db
  class Bar < ::Bar
    extend OtherDb::Base
  end
end