Pratik
2006-Jun-20 12:39 UTC
[Rails] Maintaining same session for a user across different PCs
Hi, I''m trying to make a simple shopping cart, where I want to maintain state when a use logs in from different location. Consider the following : 1. ''foo'' logs in from home pc and add ''bar'' item to the cart. 2. ''foo'' goes to office and logs in from office PC. 3. Now I want only one session for ''foo'', so that when he logs in from office PC, he sees ''bar'' already added in his shopping cart. I can probably store session id in User table. But I''m not sure how to go about this. Any inputs would be great. Thanks, Pratik -- rm -rf / 2>/dev/null - http://null.in
James Ludlow
2006-Jun-20 14:40 UTC
[Rails] Maintaining same session for a user across different PCs
On 6/20/06, Pratik <pratiknaik@gmail.com> wrote:> I''m trying to make a simple shopping cart, where I want to maintain > state when a use logs in from different location. Consider the > following : > > 1. ''foo'' logs in from home pc and add ''bar'' item to the cart. > 2. ''foo'' goes to office and logs in from office PC. > 3. Now I want only one session for ''foo'', so that when he logs in from > office PC, he sees ''bar'' already added in his shopping cart. > > I can probably store session id in User table. But I''m not sure how to > go about this.You don''t really need to maintain a single session here. You should consider storing the cart in the database, rather than keeping it only in memory in the session. -- James
Mike Berrow
2006-Jun-20 15:20 UTC
[Rails] Re: Maintaining same session for a user across different PCs
Pratik <pratiknaik@...> writes:> I''m trying to make a simple shopping cart, where I want to maintain > state when a use logs in from different location. Consider the > following : > > 1. ''foo'' logs in from home pc and add ''bar'' item to the cart. > 2. ''foo'' goes to office and logs in from office PC. > 3. Now I want only one session for ''foo'', so that when he logs in from > office PC, he sees ''bar'' already added in his shopping cart. > > I can probably store session id in User table. But I''m not sure how to > go about this.Hello Pratik, A ''session'' in Rails (and also in anything else using CGI::Session) is tied to a session_id. This gets ''born'' everytime a browser currently unknown to Rails sends a request to the web server. ''Unknown'' in this sense means that the browser does not (currently) have a cookie called ''_session_id'' (or, if it does, the value of it does not match any currently known session). If the browser instance does not have this matching session id, then it gets given one right away (and a matching session object is created on the rails side). [Aside: The session objects are identified by an id (not a number) that is generated by the cgi module. The id is generated in such way as to be one-time unique. It does this by creating (by default) a 32 hex character key (which means there are 16^32 possible combinations). It is an MD5 hash based upon the time, a random number, and a constant string. An example is "d53cb20abe8c3d11". ] The _session_id cookie is set to last for the life of the browser. It does not go away until the user closes the browser (or manually deletes it). Just logging out (but leaving the browser open) will leave the session around. The upshot of all this is that information in the session object is normally only available to that specific browser session. So, in your scenario, logging in on another browser will not (of itself) make that information available to the newly logged in browser (in fact that will generate its own new session). To keep information persisted for an indentified user, you are going to have to put it into a db table (easy enough) or a file (harder). To get the current session values persisted in this way, I see a number of options: [1] Know which specific values you want to store and keep them current in the db as the session values are updated. [2] Assuming the user logs out cleanly (hard to rely on), the logout action could grab the session file and store it in a column in the user table. Then on re-login somewhere else, it could be pulled out and used the replaces the contents of the new (initial) session file. This would require direct reads and writes to session files and would likely be frowned on since you really need to know more lower level details. [3] Unmarshall the session file and convert the resulting hash to (say) YAML and store that in the user table. Then, on the fresh login, bring the values back from YAML and replace specific session values from that. It''s all pretty tricky, but such a ''session tranference'' is going beyond what sessions were built for (ephemeral browser state). You can get the session_id like this: cookies[:_session_id] # Session files are kept in: SessDir = RUBY_PLATFORM =~ /mswin32/ ? ENV[''TEMP''] : ''/tmp'' # prior to Rails 1.1, and for Rails 1.1 SessDir = ActionController::Base.session_options[:tmpdir] You can grab session files like this: files = Dir.glob("#{SessDir}/ruby_sess.*") # the suffix is the session_id. e.g. ruby_sess.d53cb20abe8c3d11 # Load them up like this: sess = Marshal.load(File.read(sfile)) # Set values: sess["hash"][:expired] = ''true'' # Write them back ssfile = File.open(sfile, "w+") ssfile.write(Marshal.dump(sess)) ssfile.close -- Mike Berrow
Pratik
2006-Jun-21 10:09 UTC
[Rails] Re: Maintaining same session for a user across different PCs
Thanks a lot Mike for your detailed reply. That helped a lot :) -Pratik On 6/20/06, Mike Berrow <mberrow1@pacbell.net> wrote:> Pratik <pratiknaik@...> writes: > > > I''m trying to make a simple shopping cart, where I want to maintain > > state when a use logs in from different location. Consider the > > following : > > > > 1. ''foo'' logs in from home pc and add ''bar'' item to the cart. > > 2. ''foo'' goes to office and logs in from office PC. > > 3. Now I want only one session for ''foo'', so that when he logs in from > > office PC, he sees ''bar'' already added in his shopping cart. > > > > I can probably store session id in User table. But I''m not sure how to > > go about this. > > Hello Pratik, > > A ''session'' in Rails (and also in anything else using CGI::Session) > is tied to a session_id. This gets ''born'' everytime a browser > currently unknown to Rails sends a request to the web server. ''Unknown'' > in this sense means that the browser does not (currently) > have a cookie called ''_session_id'' (or, if it does, the value of it does not > > match any currently known session). If the browser instance does not have this > > matching session id, then it gets given one right away (and a matching session > > object is created on the rails side). > > [Aside: The session objects are identified by an id (not a number) > that is generated by the cgi module. The id is generated in such way > as to be one-time unique. It does this by creating (by default) a 32 > hex character key (which means there are 16^32 possible combinations). > It is an MD5 hash based upon the time, a random number, and a > constant string. An example is "d53cb20abe8c3d11". ] > > The _session_id cookie is set to last for the life of the > browser. It does not go away until the user closes the browser > (or manually deletes it). Just logging out (but leaving the > browser open) will leave the session around. > > The upshot of all this is that information in the session object > is normally only available to that specific browser session. > So, in your scenario, logging in on another browser will not > (of itself) make that information available to the newly logged > in browser (in fact that will generate its own new session). > > To keep information persisted for an indentified user, you are > going to have to put it into a db table (easy enough) or a file > (harder). To get the current session values persisted in this way, > I see a number of options: > > [1] Know which specific values you want to store and keep > them current in the db as the session values are updated. > > [2] Assuming the user logs out cleanly (hard to rely on), > the logout action could grab the session file and store it > in a column in the user table. Then on re-login somewhere > else, it could be pulled out and used the replaces the contents > of the new (initial) session file. This would require direct > reads and writes to session files and would likely be frowned > on since you really need to know more lower level details. > > [3] Unmarshall the session file and convert the resulting hash > to (say) YAML and store that in the user table. Then, on the > fresh login, bring the values back from YAML and replace > specific session values from that. > > It''s all pretty tricky, but such a ''session tranference'' is going > beyond what sessions were built for (ephemeral browser state). > > You can get the session_id like this: cookies[:_session_id] > > # Session files are kept in: > SessDir = RUBY_PLATFORM =~ /mswin32/ ? ENV[''TEMP''] : ''/tmp'' > # prior to Rails 1.1, and for Rails 1.1 > SessDir = ActionController::Base.session_options[:tmpdir] > > You can grab session files like this: > files = Dir.glob("#{SessDir}/ruby_sess.*") > # the suffix is the session_id. e.g. ruby_sess.d53cb20abe8c3d11 > > # Load them up like this: > sess = Marshal.load(File.read(sfile)) > # Set values: > sess["hash"][:expired] = ''true'' > # Write them back > ssfile = File.open(sfile, "w+") > ssfile.write(Marshal.dump(sess)) > ssfile.close > > -- Mike Berrow > > > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- rm -rf / 2>/dev/null - http://null.in