Mysql Rails Web API中的单模式多租户

Mysql Rails Web API中的单模式多租户,mysql,ruby-on-rails,ruby,schema,multi-tenant,Mysql,Ruby On Rails,Ruby,Schema,Multi Tenant,我有一个单一的客户端应用程序-Angular JS前端和一个带有MySQL DB的Rails API后端。我正在尝试将应用程序转换为单模式多租户应用程序。我读了很多书,并且: 如果可能的话,我不想使用gem-plant,它是多个模式,并且使用Postgres不符合要求,而且act_as_tenant似乎使用Thread.current来识别我不想做的租户 我已经读到,默认的_范围也不应该被使用,原因很多,我在这里不想讨论 我将请求头中的租户令牌从前端传递到Rails后端,并使用租户令牌在Ap

我有一个单一的客户端应用程序-Angular JS前端和一个带有MySQL DB的Rails API后端。我正在尝试将应用程序转换为单模式多租户应用程序。我读了很多书,并且:

  • 如果可能的话,我不想使用gem-plant,它是多个模式,并且使用Postgres不符合要求,而且act_as_tenant似乎使用Thread.current来识别我不想做的租户
  • 我已经读到,默认的_范围也不应该被使用,原因很多,我在这里不想讨论
我将请求头中的租户令牌从前端传递到Rails后端,并使用租户令牌在ApplicationController中标识租户。我现在正在找出读取和写入数据的最佳方法,以便与发出请求的租户相关联

排除了上述选项后,我能看到的唯一选项是进入我的所有控制器方法,并在写入和读取数据的任何地方更新它们。我更愿意对我的每个模型应用某种回调,以便在写入数据时始终写入租户id,在读取数据时始终将租户id用作过滤器

考虑到我无法访问模型中的租户令牌,除了更新所有控制器方法之外,我不知道如何进行此操作,这将是一个艰巨且容易出错的过程


提前谢谢

不使用默认范围是一个好主意-它的行为类似于一个黑匣子,可能会破坏整个过程,尤其是如果你做过任何偏执删除的事情

做你要求的事情的一种方法是使用。您可以在web请求开始时定义租户id令牌,然后在web请求期间通过class属性访问它。这将在租户模型上创建线程安全属性访问器

在控制器中,您可以检测当前请求的租户(使用子域或令牌),并设置token.current_id变量。此变量将在请求期间可用。请注意,它不会自动用于任何后台作业或其他进程,因为该变量设置在当前线程内

在中使用作用域演示了此方法,但您不必使用作用域。您可以设置一个助手方法,如
current\u-tenant
,然后明确限定所有查询的范围,如
current\u-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
#models/tenant.rb
类租户<应用程序记录
线程访问器:当前线程id
# ...
结束
#控制器/应用程序\u controller.rb
类ApplicationController
不使用默认范围是个好主意-它的行为就像一个黑匣子,可能会破坏整个过程,特别是如果你曾经做过任何偏执删除的事情

做你要求的事情的一种方法是使用。您可以在web请求开始时定义租户id令牌,然后在web请求期间通过class属性访问它。这将在租户模型上创建线程安全属性访问器

在控制器中,您可以检测当前请求的租户(使用子域或令牌),并设置token.current_id变量。此变量将在请求期间可用。请注意,它不会自动用于任何后台作业或其他进程,因为该变量设置在当前线程内

在中使用作用域演示了此方法,但您不必使用作用域。您可以设置一个助手方法,如
current\u-tenant
,然后明确限定所有查询的范围,如
current\u-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
#models/tenant.rb
类租户<应用程序记录
线程访问器:当前线程id
# ...
结束
#控制器/应用程序\u controller.rb
类ApplicationController
我推荐Ryan Bigg的书,书名为Leanpub。谢谢!不过,我有几个问题:既然已经确定了当前租户,那么如何更新我的其他模型,以便在读取数据时写入当前租户id并将其用作过滤器?当前_tenant.id或tenant.current_id是否可用于这些模型,例如-用户模型?您可以使用当前_tenant变量确定所有查询的范围。例如
current\u tenant.users.find(params[:id])
。既然您已经将当前租户定义为帮助方法,您也可以在视图中使用它。我推荐Ryan Bigg的书,书名为Leanpub。谢谢!不过,我有几个问题:既然已经确定了当前租户,那么如何更新我的其他模型,以便在读取数据时写入当前租户id并将其用作过滤器?当前_tenant.id或tenant.current_id是否可用于这些模型,例如-用户模型?您可以使用当前_tenant变量确定所有查询的范围。例如
current\u tenant.users.find(params[:id])
。由于您已将
current\u tenant
定义为助手方法,因此也可以在视图中使用它。