Почему переменные потоков в Rails прерывисты?

В моем контроллере приложений есть следующее:

before_filter :set_current_subdomain

  protected
    def set_current_subdomain
      Thread.current[:current_subdomain] = current_subdomain
      @account = Account.find_by_subdomain(current_subdomain)
    end

    def current_subdomain
      request.subdomain
    end

а затем в некоторых из моих моделей:

default_scope :conditions => { :account_id => (Thread.current[:account].id unless Thread.current[:account].nil?) }  

Теперь это работает - иногда. Например, я загружаю индексный метод и возвращаю список записей с применяемой областью, но иногда иногда получаю пустой список, поскольку Thread.current [: account_id] выводится как ноль, даже если запросы, запрошенные ранее в запросе, работают используя то же значение.

Вопрос в том, почему это не работает, и есть ли лучший способ установить переменную глобальную для текущего запроса?

Ответ 1

Манипуляция локальными переменными Thread - очень плохая идея, и она не приведет ни к чему, кроме грусти, душевной боли и боли. Там нет гарантии, что разные части обработки запроса будут обрабатываться одним и тем же потоком, и из-за этого ваши переменные могут потеряться.

Соглашение Rails заключается в создании переменных экземпляра в контексте ApplicationController. Проще говоря, все, что вы действительно делаете, это:

class ApplicationController < ActionController::Base
  before_filter :set_current_subdomain

  attr_reader :current_subdomain
  helper_method :current_subdomain

protected
  def set_current_subdomain
    @current_subdomain = request.subdomain

    @account = Account.find_by_subdomain(@current_subdomain)
  end
end

Любые переменные типа @..., которые вы создаете, будут привязаны к экземпляру ApplicationController, связанному с текущим запросом. Важно отметить, что каждый запрос будет выпущен совершенно новый экземпляр соответствующего класса контроллера.

Вы можете создавать любые переменные экземпляра, которые вы хотите, если они каким-то образом не конфликтуют с теми, которые используются самими Rails, но в общих чертах это происходит нечасто, и конфликты обычно возникают вместо имен методов.

Переменные экземпляра класса будут сохраняться между запросами в средах, где включен флаг "Кэш-классы". В среде разработки ваш класс контроллера перезагружается каждый раз, когда выполняется запрос, чтобы он отражал текущее состояние ваших исходных файлов.