如何解决Marshal.dump“没有为类Proc定义marshal_dump”错误

时间:2011-01-12 11:03:26

标签: ruby-on-rails ruby serialization

假设我有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)?

3 个答案:

答案 0 :(得分:5)

通常最好将用户 id 存储在会话中,而不是User实例本身。这意味着您必须对经过身份验证的请求执行db(或memcache)查找,但它可以为您节省大量有关序列化/缓存的麻烦,否则您将无法处理。

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

答案 1 :(得分:1)

对于这个特定情况,我会说,只存储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

答案 2 :(得分:0)

尝试在会话中存储未保存的AR对象时遇到此问题。 由于我在处理任意模型,因此我必须存储类和属性 在会话中,以便我以后可以重建它。我通过一起保存会话中的类和属性来解决这个问题:

session[:key] = {:klass => obj.class.to_s, :attributes => obj.attributes}

然后我可以从会话中重新创建对象

obj = session[:key][:klass].constantize.new(session[:key][:attributes])