在Rails cookie中存储/检索值

时间:2011-04-24 11:41:22

标签: ruby-on-rails ruby-on-rails-3 cookies

我创建了一个看起来或多或少的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

然后它被包含到Application控制器中,并在每个请求之前在过滤器中被触发:

create_cookie unless cookie_exists?

我的网站不使用身份验证,我想显示由访客创建的最近项目。 所以,在一个Item控件中我有这样的东西:

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

问题如下:

  • 前过滤器创建一个空的 cookie,我可以确认它是最初的 值设置为[](确定)
  • 在用户创建项目之后,我希望cookie数组有一个额外的值,但它会变成Nil,并且不存在任何内容(BAD)。它甚至没有例外。

我在哪里犯了错误?我应该如何向cookie添加新值? 此外,检查cookie存在的首选方法是什么?看来#has_key?方法不可用。

有些问题:

因为我想显示客人项目的链接(存储在cookie中),其形式为:

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

我是否应该在#create操作中创建链接并将其存储在cookie中?或者我应该保留我知道的ID,以生成它们?我担心cookie可能无法存储这样的链接(因此我最初想到只存储ID)

提前致谢

编辑:似乎无法将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中存储内容的首选方式。纯ID或链接?

2 个答案:

答案 0 :(得分:2)

我最近遇到了类似的问题并通过创建一个隐藏所有cookie哈希交互的CookieCollection类来解决它,并允许您像使用Array一样从集合中添加和列出。它通过控制器方法和帮助程序公开。

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

答案 1 :(得分:1)

如果Item模型不重要,请不要将其加载到cookie中。有大约2k的cookie限制,数据的序列化将很快进入。在任何情况下,都应该对数据库(或其他东西)进行持久化,并且只需要将最少量的会话状态放入cookie中。项目被创建到数据库中。如果要加载客户端项目,请使用javascript。

即使你有访客项目,只需将其加载到数据库中并以某种方式标记它。 IE:放入一个guest表,或者有一个设置guest = 1的列或者有一个foreign_key到guest_items表或其他东西。实际上(即使使用匿名身份验证),会话只具有当前用户ID(在您的情况下,没有任何内容)。我假设你试图坚持使用永久性cookie来“记住我”类型的功能,这没关系。抽象层有点奇怪。简单系统中的首选方法是:

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

坚持使用数据库,仅将会话存储在cookie中。