An object stored in a Rails session becomes a string?

Normally, I will not store objects in a Rails session, but I use a library that requires this. I ran into a very strange problem when a stored object appears as a string after a redirect.

To reproduce, I created a sample Rails 4.1 application

$ rails new session-test

Added test controller:

 class HomeController < ApplicationController def index logger.debug "session[:customer]: #{session[:customer]}" logger.debug "session[:customer].name: #{session[:customer].name}" end def from Struct.new 'Customer', :name, :address session[:customer] = Struct::Customer.new 'Dave', '123 Main' redirect_to :action => :index end end 

configuration routes:

 Rails.application.routes.draw do get 'home/index' get 'home/from' root 'home#index' end 

Then I run Rails

$ bundle exec rails server

and click localhost: 3000 / home / from in the browser:

 Started GET "/home/from" for 127.0.0.1 at 2014-04-09 21:20:25 -0700 Processing by HomeController#from as HTML Redirected to http://localhost:3000/home/index Completed 302 Found in 18ms (ActiveRecord: 0.0ms) Started GET "/home/index" for 127.0.0.1 at 2014-04-09 21:20:25 -0700 Processing by HomeController#index as HTML session[:customer]: #<struct Struct::Customer name="Dave", address="123 Main"> Completed 500 Internal Server Error in 2ms NoMethodError (undefined method `name' for "#<struct Struct::Customer name=\"Dave\", address=\"123 Main\">":String): app/controllers/home_controller.rb:4:in `index' 

I do not know why this object translates as String ...

This seems to be related to the cookie_store cookie storage type, because if I change

session_store.rb of

Rails.application.config.session_store :cookie_store, key: '_session-test_session'

to

Rails.application.config.session_store :cache_store

it works!

Any ideas?

+8
ruby-on-rails ruby-on-rails-4 session shopify
source share
3 answers

You cannot store objects in a Rails session. This is a keystore that only accepts strings because, most often, it is packaged and sent to the client as an encrypted cookie.

This is not a dump for things you may need. Pay attention to how much garbage you have, because the more you rely on the session, the more cookies - the client will have to return to your server for each request.

It is worth noting the headers in your network browser checker to find out how heavy your request is.

If you really need to save something, use a string-friendly encoding format such as JSON to make sure that you can return the data in a usable format.

I would really doubt using cache_store , which does not apply to different instances of your application. Ruby objects exist only in the context of one process, so other requests, which will most often hit some random process, will not be able to use this as easily.

The default cookie store is the most reliable. Others that are shared between processes depend on additional services that are running (Memcached, Redis, etc.), but most of them also dictate a row-only policy.

+5
source share

Fix - serialize and deserialize explicitly, manually.

eg.

 # storing... session[:customer] = (Struct::Customer.new 'Dave', '123 Main').to_yaml # retrieving... customer = YAML.load(session[:customer]) 

For shopify_app gem, see the file changes in the stretch request https://github.com/Shopify/shopify_app/pull/90/files and apply it to an existing application.

+4
source share

I had the same problem with my Shopify application and it spent a lot of time debugging. Based on the tadman, an accurate, if not dogmatic explanation, I was able to get around it by combining the session object. It took only 3 lines of code:

login_protection.rb: 12: ShopifyAPI :: Base.activate_session (Marshal :: load session [: shopify]) login_protection.rb: 25: Marshal :: load session [: shopify]

sessions_controller.rb: 13: session [: shopify] = Marshal :: dump (sess)

I posted this on the Shopify forum and expect them to release an update soon. For what it's worth, I think the old way, philosophically β€œwrong,” worked correctly in every version of Rails prior to 4.1.

0
source share

All Articles