多租户应用程序中的acts_as_list - 如何设置范围?

时间:2013-11-25 21:13:12

标签: ruby-on-rails scope multi-tenant default-scope acts-as-list

问题

我在多租户应用中使用acts_as_list。我使用此Railscast模拟了多租户:#388 Multitenancy with Scopes(需要订阅)。

我需要确保我的around_filter正常工作,以便租户不会影响其他租户的数据。

如果acts_as_list忽略default_scope,最好的方法是使acts_as_list强制执行多租户?

背景

基本思想是在application_controller.rb中使用around_filter,如下所示:

class ApplicationController < ActionController::Base
  include SessionsHelper
  around_filter :update_current_tenant

  #current_tenant is defined in sessions_helper.rb, included above
  def update_current_tenant
    Tenant.current_id = current_tenant.id if current_tenant
  end
end

这样,每次在应用程序中加载页面时,都会设置current_tenant,并且我可以使用default_scope来限制只访问current_tenant的内容。像这样:

  default_scope { where(tenant_id: Tenant.current_id) }

但acts_as_list使用Model.unscoped(在本例中为Submission.unscoped),绕过我的default_scope。

这是我正在研究的具体模型:

class Submission < ActiveRecord::Base
  default_scope { where(tenant_id: Tenant.current_id) }

  acts_as_list scope: [:for_date, :tenant_id] # Works, but is this safe?

  # The one below is closer to what I want, but it bombs 
  #acts_as_list :scope => 'for_date = #{for_date} AND tenant_id = #{Tenant.current_id}'
end

我在其他一些地方这样做,但我使用id列而不是for_date,所以acts_as_list声明如下:

acts_as_list :scope => 'task_id = #{task_id} AND tenant_id = #{Tenant.current_id}'

效果很好。但是当我使用我的Submission模型尝试这个,并在acts_as_list范围中包含for_date时,我收到此错误:

PG::UndefinedFunction: ERROR:  operator does not exist: date = integer
LINE 1: ... (submissions.position IS NOT NULL) AND (for_date = 2013-11-...
                                                           ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT  "submissions".* FROM "submissions"  WHERE (submissions.position IS NOT NULL) AND (for_date = 2013-11-25 AND tenant_id = 1) ORDER BY submissions.position DESC LIMIT 1

我如何添加这样一个明确的类型转换?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

原来我只需要转义for_date(我认为因为它是一个带有单引号的“日期”数据类型,而不是整数数据类型,但我不确定):

acts_as_list :scope => 'for_date = \'#{for_date}\' AND tenant_id = #{Tenant.current_id}'

这就是诀窍。