ActiveRecord模型同时具有两个数据库

时间:2017-09-10 19:25:41

标签: ruby-on-rails ruby activerecord

我有一个带有两个数据库后端的Ruby on Rails应用程序 - PostgreSQL和MemSQL(一个与MySQL兼容的分析数据库)。

如何设置Model以便它同时保存到两个数据库 ,以便在两者上执行CREATE,UPDATE和DELETE语句,并且仅执行SELECT查询在PostgreSQL上?

换句话说 - 如何使用相同的ActiveRecord模型维护两个数据库后端始终相同?

1 个答案:

答案 0 :(得分:1)

你可以通过拥有两个模型类来实现这一点。但是在构图和复杂性方面,缺点很多。 ActiveRecord通过将连接保存在基类中来共享连接:

class MemSQLBase < ActiveRecord::Base
  establish_connection configurations['memsql'][Rails.env]
  self.abstract_class = true
end

class Post < ApplicationRecord
  after_save :push_to_memsql!
  def push_to_memsql!
    MemSQLPost.save_or_update!(self.attributes)
  end
end

class MemSQLPost < MemSQLBase
  self.table_name = :posts
  def self.model_name
    ActiveModel::Name.new("Post")
  end
end

尴尬的部分是在Post和MemSQLPost之间共享代码,你必须使用模块,因为它们不共享基类。

可以通过monkeypatching类连接方法来避免这种情况:

# this class does nothing except holding the connection pool
class MemSQLBase < ActiveRecord::Base
  establish_connection configurations['memsql'][Rails.env]
  self.abstract_class = true
end

module MemSQLMonkeyPatch
  extend ActiveSupport::Concern

  class_methods do
    def connection_pool
      MemSQLBase.connection_pool
    end

    def retrieve_connection
      MemSQLBase.retrieve_connection
    end

    def connected?
      MemSQLBase.connected?
    end

    def remove_connection(klass = self)
      MemSQLBase.remove_connection
    end
  end
end

class Post < ApplicationRecord
  after_save :push_to_memsql!
  def push_to_memsql!
    MemSQLPost.save_or_update!(self.attributes)
  end
end

class Post < MemSQLBase
  include MemSQLMonkeyPatch
  self.table_name = :posts
end

我没有测试过这个,所以你是独自一人。