У меня многоступенчатая форма приема.
Я сохраняю данные каждого шага в объекте Rails.cache, используя session.id в качестве ключа.
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
Это работает в режиме разработки.
Однако мои тесты терпят неудачу, потому что session.id равен нулю.
Я включил кеширование в файле среды test.rb:
config.action_controller.perform_caching = true
config.cache_store = :memory_store
Тем не менее, я все еще получаю ноль для session.id.
Единственное плохое решение, которое я нашел, это использовать следующий метод в контроллерах:
def session_id
@session_id ||= Rails.env.test? ? :test : session.id
end
Есть ли способ получить идентификатор объекта сеанса во время тестов рельсов?
Вы получаете session.id только тогда, когда сохраняете что-то в сеансе, иначе это nil. По первому запросу в сеансе еще ничего не хранится. После того, как ваше действие контроллера выполнено, rails сохраняет _csrf_token и, следовательно, session_id также сохраняется. Просто выньте:
<%= csrf_meta_tags %>
Из вашего макета и session.id никогда не будут инициализированы (если у вас нет другого сеанса обновления).
Идентификатор сеанса ничего особенного но вам, вероятно, следует создать свой собственный ключ для этой цели:
# it's what session id is anyway
session[:cache_id] ||= SecureRandom.hex(16)
Вы также можете сохранить что-то в сеансе, и id инициализирует:
# 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"
Что касается теста, он просто показывает, что session.id не является надежным источником идентификатора вашего кеша. Исправьте это в контроллере с самого начала.
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
Это как зайти на страницу в первый раз. Попробуйте в окне инкогнито, session.id будет nil, но только при первом посещении. В тесте это всегда первое посещение.
@chell см. обновление. надеюсь, что это делает его более ясным.
Спасибо за то, что сделали это намного яснее. Я добавил session.update({}).to_h для инициализации сеанса, и он работает.
Спасибо за ваш ответ @Alex. Когда я запускаю это в dev, я инициализирую session.id пустым хешем (см. мой ответ). На данный момент у меня есть идентификатор сеанса. Однако, когда я запускаю свои тесты, которые также вызывают метод инициализации, session.id равен нулю. Вот почему мне пришлось добавить Rails.env.test? ? :test : session.id, который я бы предпочел не использовать. Итак, мой вопрос остается, почему, когда я запускаю свои тесты, у меня нет значения session.id?