I have a multi-step intake form.
I store the data from each step in a Rails.cache object using the session.id as the key.
def initialize_cache
Rails.cache.fetch(session.id) { Hash.new }
end
def add_params_to_cache
attrs = Rails.cache.read(session.id).merge(user_profile_params)
Rails.cache.write(session.id, attrs)
end
This works in development mode.
However, my tests fail because the session.id is nil.
I have enabled caching in the test.rb environment file:
config.action_controller.perform_caching = true
config.cache_store = :memory_store
However, I still get nil for session.id.
The only poor solution I have found is to use the following method in the controllers:
def session_id
@session_id ||= Rails.env.test? ? :test : session.id
end
Is there a way to get the session object id during rails tests?
CodePudding user response:
You only get session.id
when you store something in session, otherwise it's nil
. On the first request there is nothing stored in session yet. After your controller action is done, rails stores _csrf_token
and so session_id
is stored as well. Just take out:
<%= csrf_meta_tags %>
from you layout and session.id
will never be initialized (unless you have something else updating session).
Session id is nothing special but you should probably create your own key for this purpose:
# it's what session id is anyway
session[:cache_id] ||= SecureRandom.hex(16)
You can also save something into session and id
will initialize:
# assuming there is no session
cookies.clear
session.id #=> nil
# any one of these will initialize session id
session.update({})
session.send(:load!)
session[:touch] = "poke"
# or this
session.destroy
session.clear
session.id #=> "cc3363adc0831258d3173f207a62dcae"
As far as the test is concerned, it's just showing you session.id
is not a reliable source for your cache id. Fix it in the controller from the start.
class HomeController < ApplicationController
def index
p "this does not initialize session.id"
p Rails.cache.fetch(session.id) { Hash.new }
p session.id # still nil
p
p "this will initialize session"
p session.update({}) # or any other way mentioned above
p Rails.cache.fetch(session.id) { Hash.new }
p session.id
end
end
$ bin/rails test test/controllers/home_controller_test.rb
Running 1 tests in a single process (parallelization threshold is 50)
Run options: --seed 48575
# Running:
"this does not initialize session.id"
{}
nil
"this will initialize session"
{"session_id"=>"39c1ee00e1e9214250d0bb6cfbfa68dc"}
{}
"39c1ee00e1e9214250d0bb6cfbfa68dc"
.
Finished in 0.294108s, 3.4001 runs/s, 3.4001 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
This is like visiting the page for the very first time. Try in incognito window, session.id
will be nil
, but only the first visit. In a test it's always the first visit.