it-swarm.com.ru

Как заставить этот сеанс загружаться?

Я работаю над приложением, которое должно использовать информацию идентификатора сеанса. Моя сессия хранится в куки. У меня проблема в том, что мой сеанс не сразу доступен контроллеру, когда пользователь впервые заходит на сайт. Я думаю, что я могу что-то упустить из-за того, как сеансы инициализируются в 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="}
13
joscas

Я нашел способ форсировать инициализацию сессии. Доступ к сеансу, очевидно, не вызывает инициализацию, но запись в сеанс делает. Что я делаю в моем контроллере, так это сейчас:

class MyController < ApplicationController
  protect_from_forgery
  def index
    session["init"] = true
    do_stuff
  end
end

Тем не менее я не уверен, следует ли считать это нормальным поведением в Rails. Мне кажется неправильным писать в сеанс для инициализации. Чтения должно быть достаточно.

20
joscas

Я согласен с ответом @joscas, но вместо записи значения я бы удалил его, чтобы не иметь избыточных данных.

class MyController < ApplicationController
  protect_from_forgery
  def index
    session.delete 'init'
    do_stuff
  end
end

Сессия загружается таким же образом.

Примечание: Убедитесь, что вы не используете ключ, который будет удален в вашем приложении.

7
Lazarus Lazaridis

Вот некоторый соответствующий код из ActionDispatch :: Session :

 def [](key)
    load_for_read!
    @delegate[key.to_s]
  end

  private

  def load_for_read!
    load! if !loaded? && exists?
  end

Это означает, что объект сеанса будет загружен, как только вы получите доступ к любому значению по его ключу через [].

5
zetetic

Я не очень понимаю ваш вопрос. Если вам требуется, чтобы пользователь зарегистрировался или вошел в систему, прежде чем получить доступ к сайту, проблем не должно быть. При создании пользователя его информация сразу сохраняется в куки. Например:

Пользовательский контроллер: (регистрация осуществляется через # новых пользователей)

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

Контроллер сеансов: (вход в систему осуществляется через сеансы # new)

 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
0
Peter de Ridder