Headache with sessions being shared.

I have a really horrendous problem with sessions.

before_filter :find_cart_from_session

private
def find_cart_from_session
    if session[:cart] # if there's is a cart in the session
      begin
        @cart = Cart.find(session[:cart]) # return existing or new cart
      rescue ActiveRecord::RecordNotFound
        @cart = Cart.create
        @cart.save
        session[:cart] = @cart.id # add a new one
      end
    else
      @cart = Cart.create
      @cart.save
      session[:cart] = @cart.id # add a new one
    end
    @cart
end

This code works.
I mean it will return the cart object but ...

2 different computers add the same product to their cart whoever gets
the product in first get both products.

user 1 adds product 1
user 1 sees 1 product in their cart

user 2 adds product 1
user 2 sees no products
user 1 refreshes and now sees two product 1's in their cart.

user 2 adds product 2
user 2 should now have 1 x product 1 and 1 x product 2
But user 2 has 0 x product 1 and 1 x product 2

user 1 now adds product 2 to their cart
user 2 refreshes and has 2 x product 2

Now at this point both user 1 and user 2 should have 1 of each prioduct
in their cart.
Controller action for this is

  def add_to_cart
    product = Product.find(params[:id])
    @cart = find_cart
    @cart.add_product(product)
    redirect_to_category_menu
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid product #{params[:id]}" )
    redirect_to_category_menu 'Invalid product'
  end

I'm using database storage for the session.
This is a total nightmare and I have just lost all my confidence in
Rails even though this may be something wrong with the way I have set up
the environment this surely should not be allowed to happen.
Any ideas on what I have got wron or should be looking at?

Thanks

James

First thing I'd do is run in development mode and double check what
sql statements are being sent to the database to find those sessions.
I've been working only with cookie sessions, so naturally I'd suspect
that.

Then place a debugger statements here:

def find_cart_from_session
    debugger
    if session[:cart] # if there's is a cart in the session

and take a look at session[:cart]. Is it a blank string, what class is
it, etc.

JDevine - Thank you for the pointers.

I've tracked down the problem.

This app was upgraded from Rails 2.1.2 to 2.3.2

The session handling changed between these versions and the :secret was
moved to the config/initializers/session_store.rb

This obviously does not exist so I have created one which leads me on to
another question
Is there any way of setting the :key dynamically?

:key => some_function

def some_function
  get_the_name_of_the_app_somehow?
end

This would enable me to keep the keys unique for each application
deployment.

James

JDevine wrote:

Honestly I don't have experience with that, or even know exactly what
the key does, but I suspect that you would want the key to remain the
same for the life of the app, so you really don't want to set it
dynamically. Otherwise, every time you make a change to the app your
sessions would all be invalid, which causes nasty errors that are hard
to decipher. Set the key by hand or via a generator or something when
you create the app then leave it alone.

That works for one site but with multiple sites each key should be
unique so I need it to be set dynamically otherwise people visiting site
one will have the same key for site 2, site 3 and so on...

But I'm still struggling with the session issue so I'll worry about the
key later.

JDevine wrote:

ActiveSupport::SecureRandom.hex(64) can generate session key