问题
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