我有一个客户端应用程序 - Angular JS前端和带有MySQL DB的Rails API后端。我正在尝试将应用程序转换为单个架构多租户应用程序。我做了很多阅读并且:
我将请求标头中的租户令牌从前端传递到Rails后端,并使用租户令牌识别我的ApplicationController中的租户。我现在正在找出读取和写入数据的最佳方法,以便与发出请求的租户相关联。
排除了上述选项之后,我能看到的唯一选择是进入我的所有控制器方法,并在数据写入和读取的任何地方更新它们。我宁愿对我的每个模型应用某种回调,以便在写入数据时始终写入租户ID,并且只要读取数据,租户ID就总是用作过滤器。
鉴于我无法访问模型中的租户令牌,我不知道除了更新我的所有控制器方法之外如何继续进行此操作,这将是一个艰巨且容易出错的过程。
提前致谢!
答案 0 :(得分:0)
不使用default_scope是一个好主意 - 它表现为一种黑盒子,并且可以破坏线路,特别是如果你做任何偏执删除的事情。
执行所提问题的一种方法是使用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