views:

364

answers:

1

I'd like to store some persistent data for each browser (user settings), and don't want to require a login to use the site. What's the bset way to achieve this?

I've considered two approaches:

  1. Store the info in the session cookie. The problem with this approach is that I would need to set the expiration time on the session cookie, which has the side effect of causing a user's login session to not expire when the browser closes.
  2. Store the info in the DB and store a retrieval key in a cookie on the client-side. I'm concerned about performance issues, as this would require additional queries and possibly some deserialization to retrieve the data. It looks like Rails switched its default from ActiveRecordStore a while back due to performance reasons: http://ryandaigle.com/articles/2007/2/21/what-s-new-in-edge-rails-cookie-based-sessions

What's the recommended way to achieve this?

A: 

Why not just use a non-session cookie? You can specify how long it will persist on the client, etc. See http://api.rubyonrails.org/classes/ActionController/Cookies.html

If you're concerned about the user messing with the cookie data, you can encrypt the cookie data using a technique like this (taken from http://www.neeraj.name/blog/articles/834-how-cookie-stores-session-data-in-rails):

cookie_data = {:foo => "bar"}
digest = 'SHA1'
secret = 'my_encryption_secret'
data = ActiveSupport::Base64.encode64s(Marshal.dump(cookie_data))
digest_value = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(digest), secret, data)
escaped_data_value = Rack::Utils.escape(data)
final_output = "#{escaped_data_value}--#{digest_value}"
cookies[:user_data] = final_output

and later to read the cookie data:

Marshal.load(ActiveSupport::Base64.decode64(cookies[:user_data]))
joshsz