Rails: доступ к текущему сеансу пользователя в модели ( - PullRequest
5 голосов
/ 19 марта 2011

Поддержка приложения Rails v2.3.8, развернутого на Apache с mod_passenger.

Мне нужен доступ к текущему сеансу пользователя в одной из моделей (точнее, в качестве наблюдателя-аудитора). Я знаю, что это нарушает принцип MVC. Но я должен нарушить его, так как у меня есть наблюдатель, который должен знать, кто в данный момент вошел в систему. У меня много контроллеров, и размещение звонка в Auditor logger не будет очень СУХОЙ.

Я просто пытаюсь вызвать User.current с возвращенным в данный момент авторизованным сеансом пользователя. Однако я столкнулся с проблемой с кэшированием / потокобезопасностью. Первоначальный автор использовал переменную класса (@@ current) для хранения текущего пользователя. Но это не потокобезопасно, поэтому я превратил это в

class User < AR:Base
  ...
  def self.current
    Thread.current[:user]
  end

  def self.current=(user)
    Thread.current[:user] = user
  end
  ...
end

Так что это должно быть поточно-ориентированным. А в Аудиторе-наблюдателе у меня есть звонок:

Auditor(subject, action, object)

Где я передаю User.current в качестве субъекта.

Этот код прекрасно работает в разработке, но в продуктах я получаю неправильные значения из User.current. Время от времени я получаю другую зарегистрированную запись пользователя, а не текущую. Таким образом, существует некоторая проблема с безопасностью потоков / кэшированием классов, которая все еще существует, но я не могу понять, как ее исправить.

Есть предложения? Спасибо

1 Ответ

3 голосов
/ 19 марта 2011

ActiveRecord и ActionPack совершенно разные, поэтому у вас нет доступа к сессии / куки в моделях. Если вам нужен текущий пользователь, у вас есть два варианта.

Вариант 1 - передать текущего пользователя модели

В вашем контроллере:

def index
    Audit.get_current_user(current_user)
    #where audit is your model that you will send the current_user to
end 

Вариант 2. Иметь модель пользователя, которая выполняет действие после изменения объекта пользователя.

В вашей пользовательской модели:

before_save :adjust_user

def adjust_user
    #self will be the object that was just modified aka the current user
end 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...