Rails:根据请求切换数据库连接

时间:2017-05-18 18:52:24

标签: ruby-on-rails ruby-on-rails-5

我正在运行Rails5,我有一个应用程序,我想根据子域更改数据库...使用过去的question/answer(基于Rails 3)我能够构建一些东西有点作品。我修改了我的基本模型以使用自定义连接处理程序,但它只在服务器启动时运行,而不是在每个请求上运行。

这是我的基础型号&自定义连接处理程序:

class CustomConnectionHandler < ActiveRecord::ConnectionAdapters::ConnectionHandler
  def initialize
    super
    @pools_by_subdomain = {}
  end

  # Override the behaviour of ActiveRecord's ConnectionHandler to return a
  # connection pool for the current domain.
  def retrieve_connection_pool(krass)
    # Get current subdomain somehow (Maybe store it in a class variable on
    # each request or whatever)
    # if (defined?(@@request)).nil?
    #   return
    # end
    #
    # if @@request.host == 'localhost'
    #   return
    # end
    # if @@request.subdomain.present? #&& request.subdomain != "www"
    # hard code domain for now, i have a database setup called new_site
      subdomain = 'new_site'#@@request.subdomain
    # end
    @pools_by_subdomain[subdomain] ||= create_pool(subdomain)

  end

  private
  def create_pool(subdomain)
    conf = Rails.configuration.database_configuration[Rails.env].dup
    #conf = ActiveRecord::Base.connection.instance_variable_get("@config").dup
    # The name of the DB for that subdomain...
    conf.update(:database => subdomain)
    #resolver = ConnectionSpecification::Resolver.new(conf, nil)
    # Call ConnectionHandler#establish_connection, which receives a key
    # (in this case the subdomain) for the new connection pool
    ApplicationRecord.establish_connection(conf)
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  self.connection_handler = CustomConnectionHandler.new
end

正如您在一些注释代码中看到的那样,我的意图是能够根据请求的子域(不同的客户端)切换池...但我的基本模型仅在第一个请求上运行永远不会再来所有其他模型都使用ApplicationRecord作为基础...所以我不知道该怎么做。任何人都可以帮助我实现目标吗?

1 个答案:

答案 0 :(得分:0)

对于任何发现这一点的人,我都能通过Sharding实现我想做的事情。我安装了Octopus shard gem并设置了一个像文档所示的shards.yml。然后我将此代码添加到我的应用程序控制器:

around_filter :select_shard

def select_shard(&block)
  # changes shard based on subdomain of host. 
  # if none found, it will use the default shard
  shard = 'default'.to_sym
  if request.subdomain.present?
    shard = request.subdomain.to_sym
  end
  Octopus.using(shard, &block)
end

所有设置,简单且有效!