我有一个客户端应用程序——Angular JS 前端和一个带有 MySQL 数据库的 Rails API 后端。我正在尝试将应用程序转换为单一架构 Multi-Tenancy 应用程序。我读了很多书,并且:
- 如果可能,我不想使用 gem - 公寓,它是多个模式并使用 Postgres 不符合要求,act_as_tenant 似乎使用 Thread.current 来识别我不想做的租户。
- 我读到 default_scope 也不应该被使用,原因有很多我不会在这里详述。
我将请求 header 中的租户 token 从前端传递到 Rails 后端,并使用租户 token 在我的 ApplicationController 中识别租户。我现在正在找出读取和写入数据的最佳方法,以便与发出请求的租户相关联。
排除了上述选项后,我能看到的唯一选项是进入我的所有 Controller 方法并在写入和读取数据的任何地方更新它们。我更愿意对我的每个模型应用某种回调,以便在写入数据时始终写入租户 ID,并在读取数据时始终将租户 ID 用作过滤器。
鉴于我无法访问模型中的租户 token ,除了更新我所有的 Controller 方法之外,我不确定如何继续进行此操作,这将是一个艰巨且容易出错的过程。
提前致谢!
最佳答案
不使用 default_scope 是个好主意 - 它的行为就像一个黑盒子,可能会破坏整个线路,尤其是当你对偏执删除进行任何操作时。
完成您要求的一种方法是使用 thread_mattr_accessor .您可以在 Web 请求开始时定义 tenant_id token ,然后在 Web 请求期间通过 class 属性访问它。这会在您的租户模型上创建一个线程安全的属性访问器。
在您的 Controller 中,您可以检测当前请求的租户(使用子域或 token )并设置 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
关于mysql - Rails Web API 中的单模式 Multi-Tenancy ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40777028/