Rails 用 session 保存对象的问题

lsaturn · 2012年10月15日 · 最后由 lsaturn 回复于 2012年10月18日 · 3705 次阅读

我有两个 model Store has_many :dishes Dish belong_to :store

我用 session 来保存购物车 session[:cart] ||= Cart.new

class Cart
  attr_reader :items, :key_items
  def initialize
    @items = Hash.new
    @key_items = Hash.new
  end

  def add_dish(dish)
    #binding.pry
    if @key_items[dish.store_id].nil?
      @items[dish.store_id] = Array.new
      #使用dish.store报错没找出为什么
      @key_items[dish.store_id] = dish.store
    end

    current_item = @items[dish.store_id].find{|item| item.dish == dish}

    if current_item
       current_item.increment_quantity
    else
      @items[dish.store_id] << CartItem.new(dish)
    end
  end
end

其中 add_dish(dish) 中的 @key_items[dish.store_id] = dish.store 就会出错 用 @key_items[dish.store_id] = Store.find_by_id(dish.store_id) 就不会出错

出错如下,会破坏 session 中结构 正确的 session[:cart] 的值为

{"cart"=>
  #<Cart:0x007f9ffc2dc780
   @items=
    {1=>
      [#<CartItem:0x007f9ffc2dc6b8
        @dish=
         #<Dish id: 1, store_id: 1, name: "红烧肉", count: 30, remaining_count: 30, price_cents: 1100, price_cents_currency: "CNY", image: nil, description: nil, created_at: "2012-10-11 07:38:26", updated_at: "2012-10-11 07:38:26">,
        @quantity=1>,
       #<CartItem:0x007f9ffc2db380
        @dish=
         #<Dish id: 2, store_id: 1, name: "白切鸡", count: 30, remaining_count: 30, price_cents: 1100, price_cents_currency: "CNY", image: nil, description: nil, created_at: "2012-10-11 07:38:26", updated_at: "2012-10-11 07:38:26">,
        @quantity=1>]},
   @key_items=
    {1=>
      #<Store id: 1, name: "IT厨房", created_at: "2012-10-11 07:38:26", updated_at: "2012-10-11 07:38:26", start_price_cents: 2500, start_price_cents_currency: "CNY", fare_cents: 800, fare_cents_currency: "CNY">}>,
 :@stale_state=>nil}

错误的值为

{"cart"=>
  #<Cart:0x007fa8742deeb0
   @items=
    {1=>
      [#<CartItem:0x007fa8742dedc0
        @dish=
         #<Dish id: 1, store_id: 1, name: "红烧肉", count: 30, remaining_count: 30, price_cents: 1100, price_cents_currency: "CNY", image: nil, description: nil, created_at: "2012-10-11 07:38:26", updated_at: "2012-10-11 07:38:26">,
        @new_record=false>]},
   @quantity=1>,
 :@key_items=>
  {1=>
    #<Store id: 1, name: "IT厨房", created_at: "2012-10-11 07:38:26", updated_at: "2012-10-11 07:38:26", start_price_cents: 2500, start_price_cents_currency: "CNY", fare_cents: 800, fare_cents_currency: "CNY">}}

大家可以看到错误的值里面多了 @new_record=false 所以破坏了对象结构,所以无法还原对象

请问是怎么回事啊?我查了很久了

http://guides.ruby-china.org/action_controller_overview.html#4 我看了里面的

CookieStore 能存储大约 4kb 的数据 — 相对其他方法少很多 — 但通常够用了。在 session 中存储大量数据是不被鼓励的,无论你的应用使用的是何种 session 存储方法。你尤其应该避免在 session 中存储复杂对象(任何除基本 Ruby 对象的对象,最常见的例子即模型的实例),因为服务器可能会在请求之间无法重建它们而引起错误。

session 里面存储对象就有可能出错?

利用 cookie + Cache 来实现? rails 中的 session 与 J2EE 中的实现上不一样。

两天了,还没有查出这个问题,那是相当的郁闷啊

查了三天,基本知道了问题所在。session 是通过 marshal 保存的,而 ActiveRecorder 对象又不是 marshalable 的,所以,就会出问题。查问题很辛苦,但是长 power 啊

需要 登录 后方可回复, 如果你还没有账号请 注册新账号