假设我有User < ActiveRecord::Base
。
现在,假设我想创建一个用户实例,验证它并将其存储在会话中,如果我无法保存它。
user = User.new
...
session[:new_user] = user unless user.save
...
使用ActiveRecord会话可能最终得到来自no marshal_dump is defined for class Proc
的{{1}}。
现在,解决此类序列化错误的最佳方法是什么(找到对象的“无效”Marshal.dump
对象)(通常不一定是AR)?
答案 0 :(得分:5)
通常最好将用户 id 存储在会话中,而不是User
实例本身。这意味着您必须对经过身份验证的请求执行db(或memcache)查找,但它可以为您节省大量有关序列化/缓存的麻烦,否则您将无法处理。
此外,从某种意义上说,它不是“无效”Proc
。 Proc
实例是Ruby代码和应用程序状态的容器,因此无法进行序列化。
答案 1 :(得分:1)
对于这个特定情况,我会说,只存储attributes
。 ActiveRecord::Base#attributes
返回存储在数据库中的属性的哈希值,因此几乎肯定不会包含任何Proc
个。
session[:new_user] = user.attributes unless user.save
但是,一般情况下,一种简单的方法是在您尝试编组的对象上使用inspect
。
puts obj.inspect
或等效
p obj
通常这会打印内部对象,你可以看到某些东西是否是Proc。如果您仍然无法找到它并且需要深入挖掘,则可以检查对象的所有成员变量。
obj.instance_variables.each do |var|
puts "#{var} = #{obj.instance_eval(var).inspect}"
end
答案 2 :(得分:0)
尝试在会话中存储未保存的AR对象时遇到此问题。 由于我在处理任意模型,因此我必须存储类和属性 在会话中,以便我以后可以重建它。我通过一起保存会话中的类和属性来解决这个问题:
session[:key] = {:klass => obj.class.to_s, :attributes => obj.attributes}
然后我可以从会话中重新创建对象
obj = session[:key][:klass].constantize.new(session[:key][:attributes])