act_as_list в многопользовательском приложении — как установить область действия?

Вопрос

Я использую act_as_list в многопользовательском приложении. Я смоделировал мультиарендность, используя этот Railscast: #388 Multitenancy with Scopes (подписка требуется).

Мне нужно убедиться, что мой around_filter работает, чтобы арендаторы не могли влиять на данные других арендаторов.

Каков наилучший способ применить область действия act_as_list для обеспечения мультиарендности, поскольку act_as_list игнорирует default_scope?

Фон

Основная идея состоит в том, чтобы использовать around_filter в application_controller.rb следующим образом:

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) }

Но act_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, поэтому объявление act_as_list выглядит так:

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

Это хорошо работает. Но когда я пробую это с моей моделью отправки и включаю for_date в область act_as_list, я получаю эту ошибку:

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

Как бы я добавил такое явное приведение типов? Или есть лучший способ сделать это?


person JoshDoody    schedule 25.11.2013    source источник


Ответы (1)


Оказывается, мне просто нужно было избежать for_date (я думаю, потому что это тип данных «дата», который имеет одинарные кавычки, а не целочисленный тип данных, но я не уверен):

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

Это помогло.

person JoshDoody    schedule 25.11.2013