如何解决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)查找,但它可以为您节省大量有关序列化/缓存的麻烦,否则您将不得不处理这些问题。

而且,从某种意义上说,它不是“无效”的ProcProc实例是Ruby代码和应用程​​序状态的容器,因此无法进行序列化。

对于这种特殊情况,我会说,只存储attributesActiveRecord::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])