Ruby on rails 使用会话存储我的购物车

Ruby on rails 使用会话存储我的购物车,ruby-on-rails,session,Ruby On Rails,Session,我有两种型号: Store has_many :dishes Dish belong_to :store 我使用会话存储我的购物车: 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.pr

我有两种型号:

Store has_many :dishes

Dish belong_to :store
我使用会话存储我的购物车:

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
      @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
如果
@key\u items[dish.store\u id]=store.find\u by\u id(dish.store\u id)
,转储如下所示:

{"cart"=>
  #<Cart:0x007fa8742deeb0
   @items=
    {1=>
      [#<CartItem:0x007fa8742dedc0
        @dish=
         #<Dish id: 1, store_id: 1, name: "meat", 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: "ITChef", 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">}}
{"cart"=>
  #<Cart:0x007f9ffc2dc780
   @items=
    {1=>
      [#<CartItem:0x007f9ffc2dc6b8
        @dish=
         #<Dish id: 1, store_id: 1, name: "meat", 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}
{“购物车”=>
#
[#]},
@关键项目=
{1=>
#}>,
:@stale_state=>nil}
为什么?

我跟踪rails

   39: def set_session(env, session_id, new_session, options)
    40:   with_lock(env, false) do
    41:     @pool.set session_id, new_session, options
 => 42:     session_id
    43:   end
    44: end


[1] pry(#<ActionDispatch::Session::RedisStore>)> new_session
=> {"cart"=>
  #<Cart:0x007fce3f09f3c0
   @items=
    {1=>
      [#<CartItem:0x007fce3f0e1338
        @dish=
         #<Dish id: 2, store_id: 1, name: "糖醋里脊", count: 30, remaining_count: 30, price_cents: 2250, image: nil, description: nil, created_at: "2012-10-17 06:36:59", updated_at: "2012-10-17 06:36:59">,
        @quantity=1>]},
   @key_items=
    {1=>
      #<Store id: 1, name: "it厨房", start_price_cents: 3400, fare_price_cents: 1000, average_time: nil, announcement: nil, image: "it.jpg", is_active: true, created_at: "2012-10-17 06:36:59", updated_at: "2012-10-17 06:36:59">}>,
 "_csrf_token"=>"ZEx7qGOrjq7jra/NtXkm96YCj2DrY1CHkzUHqhvqTns="}
39:def设置会话(环境、会话id、新会话、选项)
40:带锁(env,false)do
41:@pool.set session\u id,新建会话,选项
=>42:会话id
43:完
44:完
[1] pry(#)>新会话
=>{“购物车”=>
#
[#]},
@关键项目=
{1=>
#}>,
“_csrf_token”=>“ZEx7qGOrjq7jra/NtXkm96YCj2DrY1CHkzUHqhvqTns=“”}

[2]pry(#)>@pool.get session\u id
=>{“购物车”=>
#
[#]},
@key\u items=false>,
1=>
{1=>
#}}

所以元帅一定是做错了什么

您是否获得了
ActionController::Session::CookieStore::CookieSoverflow

您可以将有限的数据保存到会话中(最大3KB),因此我建议不要保存所有对象,只保存它的主键,即
id


我的意思是保存
1
而不是
#

原因可能是dish.store实际上是关联的实例,而不是store的实例
@stale_state
是关联变量

但是,
Store.find\u by\u id(dish.Store\u id)
返回一个真实的Store对象


无论如何,在会话中存储这些数据是一种不好的做法。

store和Dish使用了Money Rails Gem,这会有影响吗?我认为Dish.store和store.find_by_id(Dish.store_id)就是那个存储。find_by_id(Dish.store_id)没有对象信息Dish.store,会话知道如何封送吗?我使用Application.config.session\u store:active\u record\u store。我知道你的意思。我会这样做,但我想知道为什么会发生这种情况[1]pry(#)>store.find_by_id(1)=>#[2]pry(#)>dish.store=>#。当你在控制台中打印出对象时,调用object inspect。但会话使用封送处理序列化和反序列化数据。试试
Marshal.dump(Store.find_by_id(1))
Marshal.dump(dish.Store)
,你会看到区别。我试过了,它们都一样。我发现这篇文章,我想原因可能是封送员不知道如何在没有对象信息的情况下序列化和反序列化
[2] pry(#<ActionDispatch::Session::RedisStore>)> @pool.get session_id
=> {"cart"=>
  #<Cart:0x007fce3f9e92c8
   @items=
    {1=>
      [#<CartItem:0x007fce3f9e94d0
        @dish=
         #<Dish id: 2, store_id: 1, name: "糖醋里脊", count: 30, remaining_count: 30, price_cents: 2250, image: nil, description: nil, created_at: "2012-10-17 06:36:59", updated_at: "2012-10-17 06:36:59">,
        @quantity=:@new_record>]},
   @key_items=false>,
 1=>
  {1=>
    #<Store id: 1, name: "it厨房", start_price_cents: 3400, fare_price_cents: 1000, average_time: nil, announcement: nil, image: "it.jpg", is_active: true, created_at: "2012-10-17 06:36:59", updated_at: "2012-10-17 06:36:59">}}