在此介绍为什么将model放在session中是一个坏注意。
In this episode we’ll show you why it’s a bad idea to store a model in the session.
ruby
class UserController < ApplicationController
def prepare
session[:user] = User.find(:first)
redirect_to :action => :'show'
end
def show
@user = session[:user]
end
def update
@user = session[:user]
@user.name = 'Foo'
redirect_to :action => 'show'
end
end
UserController中的prepare将一个model存储在了session中。
上面的代码片段中,控制器有3个action。prepare
action查找出第一个user,将其存储在session中,然后跳转至show。show action从session中得到当前的用户并输出一些user的debug信息,show view代码如下。
<%= debug(@user) %> <%= link_to 'update', :action => 'update' %>
show页面中有一个update的链接。update再次从session中得到当前user,改变它的一个特性并show出来;在update中的更改只是临时的,未被写到数据库中;最终,update跳转至show,如下图
![](https://i-blog.csdnimg.cn/blog_migrate/012a4e107a821b206d91c798e7f2a3a7.png)
update后的show,显示出的数据与数据库中的数据是不同步的,数据库中的数据如下:
terminal
NooNoo:ep13 eifion$ script/console
Loading development environment (Rails 2.2.2)
>> User.first.name
=> "Eifion"
>>
数据库中,user的name仍为‘Eifion’.
验证中出现的问题:
在User模型中,对name存在非空校验(with validates_presence_of
).更新update action将name设置成空字符串,校验user是否有效,结果如下:
ruby
def update
@user = session[:user]
@user.name = ''
@user.valid?
redirect_to :action => 'show'
end
![](https://i-blog.csdnimg.cn/blog_migrate/30eeda24832594d0143c6b32985fbe93.png)
将name置成空时,会抛出校验错误;但当跳转到其他页面时,错误信息不能被保存。
正确的方式
将user_id存储在session中,controller中各个action的代码如下:
ruby
class UserController < ApplicationController
def prepare
session[:user_id] = User.find(:first).id
redirect_to :action => :'show'
end
def show
@user = User.find(session[:user_id])
end
def update
@user = User.find(session[:user_id])
@user.name = 'Foo'
redirect_to :action => 'show'
end
end
现将user_id存储在session中,每次请求均从数据库中获取数据。此时,user name的变化不会被持续的保留。
session应仅被用来存储简单的对象,如array, strings and integers.
原文地址:http://railscasts.com/episodes/13-dangers-of-model-in-session?view=asciicast