【问题标题】:How do I force expire a session if a cart_id no longer exists?如果 cart_id 不再存在,如何强制使会话过期?
【发布时间】:2013-12-02 11:41:44
【问题描述】:

我在我的应用中实现了一个购物车。

在我的ApplicationController.rb,我有这个:

before_filter :initialize_cart

  def initialize_cart
    if session[:cart_id]
      @cart = Cart.find(session[:cart_id])
    else
      @cart = Cart.create
      session[:cart_id] = @cart.id
    end
  end

我正在使用 Devise,并启用了:timeoutable

这些是我config/initializers/devise.rb 中的配置:

  # ==> Configuration for :timeoutable
  # The time you want to timeout the user session without activity. After this
  # time the user will be asked for credentials again. Default is 30 minutes.
  config.timeout_in = 30.minutes

  # If true, expires auth token on session timeout.
  config.expire_auth_token_on_timeout = true

问题是我偶尔想清扫旧车。就目前而言,一旦有一段时间没有访问购物车,它就会被删除。

但是,当用户尝试登录时 - 如果他们有一段时间没有清除 cookie - 他们会收到以下错误:

ActiveRecord::RecordNotFound at /
Couldn't find Cart with id=51

我检查了会话对象的创建或更新时间戳,但它没有 - 所以我无法检查会话的状态并删除超过 30 分钟或其他时间的会话。

这是会话对象的样子:

>> session
=> {"session_id"=>"57bkhjadksjfhaksjdhfca", "cart_id"=>51, "_csrf_token"=>"3823j42&*&@#lkjM+wKkagdabskdjfhba="}

我如何检查会话是否是最近的(比如用户 - 已登录和未登录 - 在过去一小时内做了某事),如果不是,则将其销毁?

或者我该如何以其他方式解决此问题?

【问题讨论】:

  • 也许在创建购物车时将您自己的modified 参数添加到购物车,然后查看上次修改(创建或更新)的时间
  • @dax 你能举个例子说明你的意思吗?
  • timoutable 模型有一个方法timedout? 在这种情况下不会有帮助吗?这是一个参考链接:rubydoc.info/github/plataformatec/devise/master/Devise/Models/…
  • 不确定如何在非 current_user 用户上使用它 - 即尚未登录的用户,因此我无法致电 current_user.timedout?。另外...如果我没记错的话,那只会跟踪已登录的用户。在我的应用程序中,用户无需先登录即可将内容添加到购物车中。它会在他们创建帐户之前创建一个会话。这就是我要处理的问题。

标签: ruby-on-rails ruby-on-rails-3 session devise


【解决方案1】:

我会这样做。

def initialize_cart
    begin
      @cart = Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
      flash.now = "Your cart was not found." # or whatever
      @cart = Cart.create
      session[:cart_id] = @cart.id
    end
end

【讨论】:

  • 完美...这解决了我的问题。我刚刚取出了flash.now,因为在这种情况下向他们发送消息是没有意义的。救援虽然有效。谢谢!
【解决方案2】:

目前,当您初始化购物车时,您正在这样做:

def initialize_cart
  if session[:cart_id] && Cart.find(session[:cart_id])
    @cart = Cart.find(session[:cart_id])
  else
    @cart = Cart.create
    session[:cart_id] = @cart.id
  end
end

我想你可以试试这个:

def initialize_cart
  if session[:cart_id] && Cart.find(session[:cart_id]).exists?
    @cart = Cart.find(session[:cart_id])
  else
    @cart = Cart.create
    session[:cart_id] = @cart.id
    session[:cart_modified] = @cart.updated_at
  end
end

然后访问session[:cart_modified] 参数以执行您需要的操作。您可以尝试的另一件事(可以说比我的第一个解决方案要好得多)是find_or_create_by

def initialize_cart
  @cart = Cart.find_or_create_by(session[:cart_id])
end

【讨论】:

  • 这看起来很酷,我认为它将帮助我解决未来的问题。对于已删除购物车的现有会话的所有用户/访问者怎么办。我该如何处理?
  • 对不起,你是什么意思?我认为这将由if session[:cart_id] 处理,对吧?但也许我只是不明白:)
  • 那么它将无法修改session 对象,因为它找不到[:cart_id] 记录,因为它不存在。已经扫过了。
  • 正确 - 因此它将转到 if 语句的 else 部分并为该用户创建一个新购物车。您只是删除/修改 :cart_id 参数,而不是整个会话
  • 不,但问题是,如果用户将会话存储在计算机上的 cookie 中,它将找到具有cart_id 属性的会话。所以它将通过if 检查if session[:cart_id]。然后它将加载页面并在 Cart 表中查找记录 - 这是它返回 not found AR 错误的时间。
猜你喜欢
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 2013-10-06
  • 1970-01-01
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多