2

I use session to store my shopping cart object

in my cart model I have

def initialize
    @items = Array.new
end

def clean
    @items = Array.new
end 

I want to use session to store whole cart object so I can use the method above

like this

@cart = session[:cart] ||= Cart.new

but my @cart output is strange

first time run it output

<%= @cart %>
#<Cart:0x007efc844d3af0>

<% @cart.clean %>
true

everything is fine, but the second time it output the object's content

<%= @cart %>
{"items"=>[]}

<% @cart.clean %>
undefined method `clean'

Can session store the whole object?

Or there is something I did wrong?

Thanks.

EDIT:

<% session[:cart] = Cart.new %>
<%= session[:cart] %>
#<Cart:0x007efc868be0a0>

<% session[:cart] = session[:cart] ||= Cart.new %>
<%= session[:cart] %>
#<Cart:0x007efc868be0a0> #Because session[:cart] does not exist
<% session[:cart] = session[:cart] ||= Cart.new %>
<%= session[:cart] %>
{"items"=>[]} #Session does not store the cart object but store the cart object's content

EDIT 2:

<% @cart = session[:cart] ||= Cart.new %>
<%= @cart %> #session[:cart] is nil so print Cart.new
<br>
<% session[:cart] = Cart.new %>
<% @cart = session[:cart] ||= Cart.new %>
<%= @cart %> #session[:cart] isn't nil so print session[:cart]

I got both two outputs are Cart object

when I refresh the page and run the same code

<% @cart = session[:cart] ||= Cart.new %>

@cart should be the session[:cart] because the session is not nil and the session[:cart] should be Cart object but it output "{"items"=>[]}"

EDIT 3:

First time:

<%= session[:cart] %>
-> nil
<% session[:cart] = Cart.new %>
<%= session[:cart] %>
-> <Cart:0x00000007c112c0>

Second time:

<%= session[:cart] %>
-> {"items"=>[]} #Why it isn't a Cart object after I refresh?
<% session[:cart] = Cart.new %>
<%= session[:cart] %>
-> <Cart:0x00000007c112c0>
Donald Chiang
  • 167
  • 1
  • 1
  • 14
  • Can session store a Cart object? I want to let both `session[:cart].clean` and `@cart.clean` works, thanks. – Donald Chiang Apr 06 '16 at 05:21
  • 1
    Storing object in session is not a good idea see http://stackoverflow.com/questions/1095714/storing-objects-in-a-session-in-rails. This thread discusses the pitfalls of it. If you insist on storing object in session, you would have to reconstruct it by passing params to Cart.new(session[:cart]) or something similar, since session serializes object and stores it. Hope this helps. – Shishir Apr 06 '16 at 05:34
  • @Shishir Thanks for help, I don't want to store cart items to the database, so I put the cart object to session and the cart object is a small array to store product id and quantity. I don't understand why I refresh the page I get the different output of session. Please see EDIT 2, thanks. – Donald Chiang Apr 06 '16 at 06:00
  • 1
    The first render, its on server side, they still ruby objects. On refresh, session is taken from the client side and deserialized. see this http://stackoverflow.com/questions/3804209/what-are-sessions-how-do-they-work for more information. – Shishir Apr 06 '16 at 06:09
  • @Shishir Thank you very much! I totally understand. So how can I store a Cart object without a database table? – Donald Chiang Apr 06 '16 at 06:37
  • Added an answer. was not able to include code here – Shishir Apr 06 '16 at 06:55

1 Answers1

3

Always use cart object. initialize it from session, do operations and in the end serialize it back to session.

    class Cart
      def initialize(params={})
        @items = params[:items] || []
      end
    end

    controller:
    @cart = Cart.new(session[:cart])
    //do operations on cart

    session[:cart] = @cart
Shishir
  • 780
  • 4
  • 9