Rails: Switch DB Connection on Request

喜你入骨 提交于 2021-02-08 08:47:58

问题


I am running Rails5, and I have an App that I want to change the DB based on the subdomain ... using this past question/answer (which is based on Rails 3) I was able to build something that kind of works. I modified my base Model to use a custom connection handler, but it only runs on server start, not on every request.

Here is my base Model & Custom Connection Handler:

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

As you can see by some of the commented code, my intent is to be able to switch the pool based on the sub domain of the request (different clients)... but my base Model is only running on the first request and never again. All other models use ApplicationRecord as their base... so I'm not sure what to do here. Can anyone help me achieve my goal?


回答1:


To anyone who finds this, I was able to achieve what I wanted to do via Sharding. I installed the Octopus shard gem and setup a shards.yml like their documentation shows. I then added this code to my application controller:

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

All set, simple and working!



来源:https://stackoverflow.com/questions/44055748/rails-switch-db-connection-on-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!