Storing Objects in a Session in Rails

Storing Objects in a Session in Rails

The main reason not to store objects in the session is that if the object structure changes, you will get an exception. Consider the following:

class Foo
attr_accessor :bar
end

class Bar
end

foo = Foo.new
foo.bar = Bar.new
put_in_session(foo)

Then, in a subsequent release of the project, you change Bar's name. You reboot the server, and try to grab foo out of the session. When it tries to deserialize, it fails to find Bar and explodes.

It might seem like it would be easy to avoid this pitfall, but in practice, I've seen it bite a number of people. This is just because serializing an object can sometimes take more along with it than is immediately apparent (this sort of thing is supposed to be transparent) and unless you have rigorous rules about this, things will tend to get flummoxed up.

The reason it's normally frowned upon is that it's extremely common for this to bite people in ActiveRecord, since it's quite common for the structure of your app to shift over time, and sessions can be deserialized a week or longer after they were originally created.

If you understand all that and are willing to put in the energy to be sure that your model does not change and is not serializing anything extra, you're probably fine. But be careful :)

Rails session store model object

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

How to store ActiveRecord object in session using Rails?

Storing objects in the session is a bad idea.

Storing Objects in a Session in Rails

Better to store the id of the object so you can always check if the object in on the latest state.

Storing and retrieving session objects

In Ruby, hash keys work by equality. You can store and retrieve a value in a hash as long as the key you're using is equal to the key that's stored.

For instance:

hsh = { 'hello' => 'world' }
p hsh['hello'] #=> "world"
'hello'.eql? 'hello' #=> true

You can retrieve the value because the same value string is always eql? in Ruby.

This is not the case for most objects:

class Example; end

object1 = Example.new
object2 = Example.new
object1.eql? object2 #=> false

Therefore, the key that you use to store in the hash must be eql? to the one that you're using to retrieve. eql? is equivalent to == and equal?.

You're creating two instances of ImportantData, which will not be equal to each other. It looks like you can accomplish what you want with a single hash key:

hash_value = ImportantData.new
hash_value.test_id = params[:test_id]
hash_value.user_id = params[:user_id]

session[:important_data] ||= hash_value
puts session[:important_data].class.name #=> ImportantData
session[:important_data].test_id #=> puts out value of test_id

Why is my ruby object being converted to a Hash after saving it in a session and how do I retain it's status as an object?

You're not meant to stuff random objects into a Rails session. Sessions are essentially a key-value store of strings, so what you're seeing is automatic flattening of objects into a form that the session can manage.

You're better off converting your object to JSON before passing it to the session and decoding it after retrieving it. In your situation, you could also just create a constructor that takes all necessary fields of your Board object as parameters and reconstruct the Board within the receiver method or use Ruby's Marshal module to get what you want.

You can also store your Board in something more persistent (cache or even database) and just pass an ID to your session. The receiver can then retrieve the row based on ID and reconstruct the object.

How OpenStruct stored in session

A session usually consists of a hash of values and a session id,
usually a 32-character string, to identify the hash. Every cookie sent
to the client's browser includes the session id. And the other way
round: the browser will send it to the server on every request from
the client.

You should either serialize your objects before storing them in the session.

session[:info] = OpenStruct.new(first_field: 1, second_field: 'two').to_yaml

and retrieve it using

YAML.load(session[:info])

from the rails documentation

Do not store large objects in a session. Instead you should store them
in the database and save their id in the session. This will eliminate
synchronization headaches and it won't fill up your session storage
space (depending on what session storage you chose, see below). This
will also be a good idea, if you modify the structure of an object and
old versions of it are still in some user's cookies. With server-side
session storages you can clear out the sessions, but with client-side
storages, this is hard to mitigate.

or change your session store from cookie_store to cache_store

In your environment change

config.session_store :cookie_store

to

config.session_store :cache_store


Related Topics



Leave a reply



Submit