Установка переменной сеанса в модели

С Rails 3, как вы можете установить переменную сеанса в модели

session[:cannot_reason] = "no such item"

Я хотел бы установить выше в моей модели пользователя. Прямо сейчас я получаю эту ошибку:

undefined local variable or method `session' for #<User:0x00000102eb9c38>

Идеи? Благодаря

Ответы

Ответ 1

Есть некоторые ненужные грузики относительно того, должны ли модели иметь доступ к данным сеанса. Я думаю, что это глупо, поскольку сеанс - это просто еще одна форма постоянного хранилища (хотя и для гораздо более короткого временного интервала), и, в Rails, кажется, что ваш объект домена также может сохраняться.

При этом не очень чистый способ сделать это должен состоять в том, чтобы передать хэш сеанса в качестве параметра в пользовательский метод, который будет работать на нем:

class User < ...
  def mymethod(session, count)
    session[:count] = count
  end
end

В вашем контроллере вы затем сделаете что-то вроде:

def update
  # ...
  user.mymethod(session, count)
end

Представляя, что mymethod реализует некоторую бизнес-логику, это соответствующим образом изменит хэш файл session. Вам не нужно передавать хэш-код session обратно контроллеру, потому что Ruby передает ссылки на объекты (например, Hash) - модификации становятся разрушительными для указанных объектов.

Слово совета. Вышеприведенный пример, на мой взгляд, вонючий. Это связано с тем, что User - это модель ActiveRecord, которая (я предполагаю) сохраняется в базе данных, и мы добавляем поведение, которое также сохраняет его в cookie сеанса. Для меня это нарушает SRP, и его следует избегать.

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

class TemporaryCart
  def initialize(session)
    @session = session
  end

  def add_item
    # ... other item adding logic
    @session[:temporary_cart][:num_items] += 1
  end
end

Теперь ваш контроллер будет выглядеть так:

def update
  # ...
  TemporaryCart.new(session).add_item
end

Это гораздо более показательно и открывает дверь для очевидного способа абстрагирования кода доступа к сеансу, если вы часто используете сеансовое хранилище. Также обратите внимание, что я переместил данные в хэш-сессии сессии (но не продемонстрировал эту реализацию). Я рекомендую вам сделать это, чтобы вы не наступали на собственные пальцы при добавлении других данных.

Ответ 2

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

Ответ 3

Объект сеанса не отображается в моделях. Либо передайте его как параметр методу в вашей модели (IMHO bad), либо определите метод в вашей модели, который возвращает то, что вы хотите, а затем сохраните его в сеансе (с вашего контроллера).

class User < ...
  def item_status
    return :no_such_item
  end
end

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

session[:item_status] = current_user.item_status