Хранение / получение значений в файле cookie Rails - PullRequest
3 голосов
/ 24 апреля 2011

Я создал модуль SessionHelper, который выглядит примерно так:

module SessionHelper

  def create_cookie
      cookies.signed[:token] = {
      :value => [],
      :expires => 1.hour.from_now
      }
  end

  def cookie_values
      cookies.signed[:token]
  end

  def add_value_to_cookie(value)
      cookies[:token] << value
  end

  def cookie_exists?
      cookies[:token].present?
  end

end

Затем он включается в контроллер приложений и запускается в фильтре перед каждым запросом:

create_cookie unless cookie_exists?

Мой сайт не использует аутентификацию, я хотел бы отобразить последние элементы, созданные гостем. Итак, в контроллере предметов у меня есть что-то вроде этого:

def create
  @item=Item.new(params[:item])
  if @item.save 
     add_value_to_cookie(@item.id)
     redirect_to @item
  else
     render :new
  end
end

Проблема заключается в следующем:

  • Фильтр before создает пустой cookie, я могу подтвердить, что он начальный значение установлено на [] (ОК)
  • После того, как пользователь создаст элемент, я ожидаю, что массив cookie будет иметь дополнительное значение, но вместо этого он превращается в ноль, и ничего не происходит (ПЛОХО). Это даже не исключение.

Где я сделал ошибку? Как мне добавить новые значения в куки? Кроме того, каков предпочтительный способ проверить наличие файла cookie? Кажется, что #has_key? метод недоступен.

Некоторые дополнительные вопросы:

Поскольку я хочу отображать ссылки на элементы гостя (хранящиеся в файле cookie), которые будут иметь вид:

link_to @item.title, item_path(@item.id)

Должен ли я просто создать ссылки в действии #create и сохранить их в файле cookie? Или я должен оставить только идентификаторы, которые я знаю, чтобы генерировать их? Я обеспокоен тем, что cookie не может хранить такие ссылки (поэтому я изначально думал о хранении только идентификаторов)

Заранее спасибо

РЕДАКТИРОВАТЬ: Кажется, что невозможно использовать cookie в качестве массива, и обходной путь должен использовать некоторую форму сериализации. Я остановился на JSON

module SessionHelper

  def set_user_cookie
    cookies.signed[:token] = {
        :value => [].to_json,
        :expires => 1.hour.from_now
    }
  end

  def user_cookie_values
    load_user_cookie_data
  end


  def user_cookie_exists?
        cookies[:token].present?
  end

  def add_to_user_cookie(value)
    current = load_user_cookie_data
    current << value
    cookies.signed[:token] = current.to_json
  end

  def remove_from_user_cookie(value)
    current = load_user_cookie_data
    current.delete(value)
    cookies.signed[:token] = current.to_json
  end

  private

  def load_user_cookie_data
    JSON.load(cookies.signed[:token])
  end

end

Хотя мне все равно было бы интересно услышать, каков предпочтительный способ хранения содержимого в cookie. Чистые идентификаторы или ссылки?

Ответы [ 2 ]

2 голосов
/ 02 августа 2013

Недавно я столкнулся с подобной проблемой и решил ее, создав класс CookieCollection, который скрывает все взаимодействия с хэшем cookie и позволяет добавлять и перечислять из коллекции, как если бы вы использовали массив.Он выставляется через метод контроллера и помощника.

http://www.swards.net/2013/08/cookie-collection-objects.html

1 голос
/ 27 января 2012

Если модель элемента нетривиальна, не загружайте ее в файл cookie.Ограничение на размер файла cookie составляет около 2 Кб, и сериализация данных быстро сработает.В любом случае, постоянство должно быть сделано для базы данных (или чего-то еще), и только минимальный объем состояния сеанса должен быть помещен в cookie.Элементы создаются в базе данных.Если вы хотите загрузить элементы на стороне клиента, используйте javascript.

Даже если у вас есть гостевые элементы, просто загрузите их в базу данных и пометьте как-нибудь.IE: положить в гостевую таблицу, или иметь столбец с настройкой guest = 1, или иметь таблицу Foreign_key для guest_items или что-то еще.На самом деле (даже с анонимной аутентификацией) у сеанса просто есть текущий идентификатор пользователя (в вашем случае - ничего).Я предполагаю, что вы пытаетесь сохранить постоянные куки-файлы для функции типа «запомни меня», это нормально.Слой абстракции немного странный.Предпочтительный способ в простой системе:

# in controller, bad idea
cookies['items'] << Item.new("whatever")

Сохранять в базе данных, сохранять сеанс только в файле cookie.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...