如何解决Marshal.dump“没有为类Proc定义marshal_dump”错误
假设我有一个User < ActiveRecord::Base
。 现在,假设我想创建一个用户实例,validation它并将其存储在会话中,如果我无法保存它。
user = User.new ... session[:new_user] = user unless user.save ...
使用ActiveRecord会话可能最终no marshal_dump is defined for class Proc
来自Marshal.dump
no marshal_dump is defined for class Proc
。
现在,解决这种序列化错误的最佳方法是什么(找到对象的“无效” Proc
对象)(通常不一定是AR)?
通常最好将用户ID存储在会话中,而不是User
实例本身。 这意味着您必须对经过身份validation的请求执行db(或memcache)查找,但它可以为您节省大量有关序列化/缓存的麻烦,否则您将不得不处理这些问题。
而且,从某种意义上说,它不是“无效”的Proc
。 Proc
实例是Ruby代码和应用程序状态的容器,因此无法进行序列化。
对于这种特殊情况,我会说,只存储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
我在尝试在会话中存储未保存的AR对象时遇到了这个问题。 由于我处理的是任意模型,我不得不在会话中存储类和属性,以便以后可以重建它。 我通过一起保存会话中的类和属性来解决这个问题:
session[:key] = {:klass => obj.class.to_s, :attributes => obj.attributes}
然后我可以从会话中重新创建对象
obj = session[:key][:klass].constantize.new(session[:key][:attributes])