我在我的两个模型中有这个:
class Weather
include Mongoid::Document
store_in database: ->{ "myapp_shared_#{Rails.env}" }
...
class Event
include Mongoid::Document
belongs_to :weather
...
这是一个多租户应用,所以我在我的应用控制器中有这个,基于子域更改数据库:
class ApplicationController < ActionController::Base
before_filter :switch_database
def switch_database
Mongoid.override_database("myapp_#{subdomain_name}_#{Rails.env}")
end
...
现在,当我运行Event.first.weather时,我在调试日志中看到了这一点:
D, [2015-09-03T18:38:18] DEBUG -- : MONGODB | myapp_subdomain_development.find | STARTED | {"find"=>"events", "filter"=>{}}
D, [2015-09-03T18:38:18] DEBUG -- : MONGODB | myapp_subdomain_development.find | SUCCEEDED | 0.025892s
D, [2015-09-03T18:38:18] DEBUG -- : MONGODB | myapp_subdomain_development.find | STARTED | {"find"=>"weathers", "filter"=>{"_id"=>BSON::ObjectId('5522c1d9526f6d6b9f0c0000')}}
D, [2015-09-03T18:38:18] DEBUG -- : MONGODB | myapp_subdomain_development.find | SUCCEEDED | 0.00078s
因此,在override_database中搜索天气,而不是在store_in数据库中搜索天气。如果我没有运行Mongoid.override_database,那么天气将从store_in中指定的app_shared_development数据库中获取。
问题是,如何使用override_database,因为这是一个多租户应用程序,但仍然强制某些模型始终使用共享数据库?
答案 0 :(得分:1)
似乎最好的解决方案是完全停止使用override_database。它有太多的副作用和无意的后果。
我简化了以下代码,但实质上这些是以下步骤:
1)我已经抽象了所有模型继承自另一个看起来像这样的类:
module XanModel
module Base
extend ActiveSupport::Concern
include Mongoid::Document
included do
store_in database: -> { DatabaseSwitcher.current_database_name }
end
2)然后在我的模型中:
class Event
include XanModel::Base
3)应用程序控制器具有:
class ApplicationController < ActionController::Base
before_filter :set_database
def set_database
DatabaseSwitcher.switch_to(subdomain)
end
4)DatabaseSwitcher有:
class DatabaseSwitcher
def self.switch_to(database_name)
Thread.current[:database_name] = database_name
end
def self.current_database_name
Thread.current[:database_name] || \
Mongoid::Threaded.database_override || \
"xanview" # fallback
end
最终结果是应用程序根据子域自动切换数据库,但某些模型可以使用全局共享数据库。