我正在开发一个需要使用会话ID信息的应用程序。我的会话存储在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
尝试在该控制器中获取会话ID:
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="}
答案 0 :(得分:20)
我找到了强制会话初始化的方法。显然,访问会话不会强制初始化,但会写入会话。我现在在控制器中做的是:
class MyController < ApplicationController
protect_from_forgery
def index
session["init"] = true
do_stuff
end
end
我还不确定这是否应该被视为Rails中的正常行为。我不得不写入会话以强制初始化。阅读应该足够了。
答案 1 :(得分:7)
我同意@joscas的答案,但我没有写一个值,而是将其删除,因为没有冗余数据。
class MyController < ApplicationController
protect_from_forgery
def index
session.delete 'init'
do_stuff
end
end
会话也是这样加载的。
注意:请确保您不要在应用程序中删除要删除的密钥。
答案 2 :(得分:5)
以下是ActionDispatch::Session的一些相关代码:
def [](key)
load_for_read!
@delegate[key.to_s]
end
private
def load_for_read!
load! if !loaded? && exists?
end
这意味着只要您通过[]
按键访问任何值,就会加载会话对象。
答案 3 :(得分:0)
我真的不明白你的问题。如果您需要用户注册或登录才能访问该站点,应该没有问题。创建用户时,他的信息会立即存储在cookie中。例如:
用户控制器:(通过用户注册#new)
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
答案 4 :(得分:0)
因此,问题可能归结为存储 session_id 的 cookie 在您尝试访问会话时尚未创建。
当您读取 session 对象时,Rails 会调用一个私有方法 session.load_for_read!
,但是,顾名思义,它只会加载 session 进行读取,如果它根本不存在,则不会实例化 session。>
另一方面,调用 session.merge!({})
(例如)会强制会话实例化。