2016-11-24 5 views
1

私は単一のクライアントアプリケーションを提供しています - Angular JSフロントエンドとMySQL DBを使用するRails APIバックエンド。私は、アプリケーションを単一のスキーマのマルチテナントアプリケーションに変換しようとしています。複数のスキーマであるとのPostgresを使用していますアパート、法案に適合していない、とact_as_tenantは、スレッドを使用するようだ - 私は可能性があれば宝石を使用したくないRails Web APIでの単一スキーマのマルチテナント

  • :私は読書をたくさん行われてきました。私がしたくないテナントを特定するための最新情報
  • default_scopeも使うべきではないと私は読んでいますが、私はここには入りません。

フロントエンドからRailsバックエンドにテナントトークンを渡しています。テナントトークンを使用して、私のApplicationControllerでテナントを識別しています。私は現在、データを読み書きするための最良の方法を考え出しているので、要求を行ったテナントに関連付けられています。

上記のオプションを除いて、私が見ることのできる唯一の選択肢は、データが書き込まれて読み込まれているところで、すべてのコントローラメソッドに入り、それらを更新することです。私はむしろ、各モデルに何らかのコールバックを適用するので、データが書き込まれるときにテナントIDが常に書き込まれ、データが読み込まれるときは常にテナントIDがフィルタとして使用されます。

モデル内のテナントトークンにアクセスできないとすれば、すべてのコントローラメソッドを更新する以外にどのように進めるべきかわかりませんが、これは面倒で間違いやすいプロセスです。

ありがとうございます!

答えて

0

default_scopeを使用しないのは良いアイデアです。ブラックボックスのように振る舞います。特に、編集的削除で何かをした場合は、ラインを壊す可能性があります。

あなたが尋ねたことをする1つの方法は、thread_mattr_accessorを使用することです。 webリクエストの開始時にtenant_idトークンを定義してから、Webリクエストの持続時間中にclass属性を使用してトークンにアクセスできます。これにより、テナントモデルにスレッドセーフなアクセサアクセサが作成されます。

コントローラでは、現在の要求(サブドメインまたはトークンを使用)のテナントを検出し、Token.current_id変数を設定できます。この変数は、リクエストの期間中利用できます。変数が現在のスレッド内で設定されているため、バックグラウンドジョブやその他のプロセスでは自動的に利用できないことに注意してください。

この方法は、this RailsCastのスコープを使って説明されていますが、スコープを使用する必要はありません。 current_tenantのようなヘルパーメソッドを設定して、current_tenant.postsのようなすべてのクエリを明示的に範囲指定することができます。

# models/tenant.rb 
class Tenant < ApplicationRecord 
    thread_cattr_accessor :current_id 
    # ... 
end 

# controllers/application_controller.rb 
class ApplicationController < ActionController::Base 

    around_action :scope_current_tenant 
    private def scope_current_tenant 
    Tenant.current_id = current_tenant.id 
    yield 
    ensure 
    Tenant.current_id = nil 
    end 

    def current_tenant 
    @current_tenant ||= Tenant.find_by_token! params[:token] 
    end 

    helper_method :current_tenant 
end 
+0

Leanpubから入手できる[Multitenancy with Rails](https://leanpub.com/multi-tenancy-rails)という本をお勧めします。 – mysmallidea

+0

ありがとう!私はいくつかの質問がありました: 現在のテナントが特定されました。データを読み込んでいるときに現在のテナントIDがフィルタとして使用されるように、他のモデルを更新するにはどうすればよいですか? current_tenant.idまたはTenant.current_idは、これらのモデルで利用できますか?たとえば、Userモデルですか? –

+0

current_tenant変数を使用してすべてのクエリをスコープできます。たとえば、 'current_tenant.users.find(params [:id])'のようになります。 'current_tenant'をヘルパーメソッドとして定義しているので、あなたのビューでそれを使うこともできます。 – mysmallidea

関連する問題