【问题标题】:ActiveRecord model with two databases simultaneouslyActiveRecord 模型同时具有两个数据库
【发布时间】:2017-09-10 19:25:40
【问题描述】:

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

如何设置Model 以便将其持久保存到两个数据库同时,以便在两者上执行 CREATE、UPDATE 和 DELETE 语句,而仅在 PostgreSQL 上执行 SELECT 查询?

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

【问题讨论】:

  • 我知道这与编程无关,但是,设计一个镜像数据库不是更简单,这样您无需在应用程序中执行另一个查询就可以拥有相同的数据吗?

标签: ruby-on-rails ruby activerecord


【解决方案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 之间共享代码,您必须使用模块,因为它们不共享基类。

可以通过猴子修补类连接方法来规避这个问题:

# 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

不过我还没有测试过,所以你自己来。

【讨论】:

  • 不过还有很多事情要做 - 您必须以某种方式将迁移应用到两个数据库(或复制它们)。有很多关于多数据库 Rails 应用程序的博客文章应该提供一个不错的起点。
猜你喜欢
  • 1970-01-01
  • 2022-06-21
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多