强制Mongoid模型始终使用特定数据库

时间:2015-09-03 17:45:49

标签: mongoid

我在我的两个模型中有这个:

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,因为这是一个多租户应用程序,但仍然强制某些模型始终使用共享数据库?

1 个答案:

答案 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

最终结果是应用程序根据子域自动切换数据库,但某些模型可以使用全局共享数据库。