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.

On Nov 1, 1:09 pm, James W. [email protected]

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:

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.

On Nov 1, 1:09�pm, James W. [email protected]

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:

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.

On Nov 1, 3:56�pm, James W. [email protected]

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.

On Nov 1, 3:56 pm, James W. [email protected]

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

2009/11/2 James W. [email protected]