Как принудительно загружается сессия?
Я работаю над приложением, которое должно использовать информацию идентификатора сеанса. Моя сессия хранится в файлах cookie. Проблема в том, что мой сеанс не сразу доступен для контроллера, когда пользователь впервые приходит на сайт. Я думаю, что мне может не хватать что-то о том, как инициализируются сеансы в Rails. Но я полагаю, что сеанс не загружен, потому что это вывод session.inspect
:
#<Rack::Session::Abstract::SessionHash:0x15cb970 not yet loaded>
Вот как воспроизвести проблему с Rails 3.2.11
и ruby 1.9.3
:
Создайте новое приложение с помощью контроллера test
:
rails new my_app
cd my_app/
rails g controller test
rm app/assets/javascripts/test.js.coffee
touch app/views/test/index.html.erb
Попробуйте получить идентификатор сеанса в этом контроллере:
class TestController < ApplicationController
def index
puts session[:session_id]
puts session.inspect
end
end
Добавьте необходимые маршруты:
MyApp::Application.routes.draw do
resources :test
end
Затем войдите в приложение и посмотрите, что он делает:
rails server
получил: http://localhost:3000/test
Это вывод в консоли:
#<Rack::Session::Abstract::SessionHash:0x3fd10f50eea0 not yet loaded>
Затем снова http://localhost:3000/test
, и на этот раз у нас есть сеанс:
400706c0b3d95a5a1e56521e455075ac
{"session_id"=>"400706c0b3d95a5a1e56521e455075ac", "_csrf_token"=>"Euaign8Ptpj/o/8/ucBFMgxGtiH7goKxkxeGctumyGQ="}
Ответы
Ответ 1
Я нашел способ принудительно инициализировать сеанс. Доступ к сеансу, по-видимому, не вызывает инициализации, но запись в сеанс делает. Что я делаю в своем контроллере, это сейчас:
class MyController < ApplicationController
protect_from_forgery
def index
session["init"] = true
do_stuff
end
end
Тем не менее я не уверен, что это должно считаться нормальным поведением в Rails. Мне не кажется, что мне нужно писать в сеанс, чтобы принудительно инициализировать. Чтения должно быть достаточно.
Ответ 2
Я согласен с ответом @joscas, но вместо того, чтобы писать значение, я удалю его, чтобы не иметь избыточных данных.
class MyController < ApplicationController
protect_from_forgery
def index
session.delete 'init'
do_stuff
end
end
Сессия также загружается.
Примечание. Убедитесь, что вы не используете ключ для удаления в приложении.
Ответ 3
Вот какой-то соответствующий код из ActionDispatch:: Session:
def [](key)
load_for_read!
@delegate[key.to_s]
end
private
def load_for_read!
load! if !loaded? && exists?
end
Это означает, что объект сеанса будет загружен, как только вы получите доступ к любому значению по его ключу через []
.
Ответ 4
Я не понимаю ваш вопрос. Если вам требуется зарегистрировать или войти в систему перед тем, как получить доступ к сайту, не должно быть никаких проблем. При создании пользователя его информация немедленно сохраняется в файле cookie. Например:
Пользовательский контроллер: (регистрация выполняется через пользователей # нового)
def create
@user = User.new(params[:user])
if @user.save
cookies.permanent[:remember_token] = user.remember_token
redirect_to root_path, notice: "Thank you for registering!"
else
render :new
end
end
Контроллер сеансов: (вход в систему осуществляется через сеансы # нового)
def create
user = User.find_by_email(params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
cookies.permanent[:remember_token] = user.remember_token
redirect_to root_path, notice: "Logged in."
else
flash.now.alert = "Email or password is incorrect."
render :new
end
end