开发者

How to resolve Marshal.dump "no marshal_dump is defined for class Proc" error

Suppose I have a User < ActiveRecord::Base. Now, suppose I would like to create a user instance, validate it and store it in t开发者_运维技巧he session if I can not save it.

user = User.new
...
session[:new_user] = user unless user.save
...

Using the ActiveRecord session one might end up with no marshal_dump is defined for class Proc coming from Marshal.dump.

Now, what is the best way to resolve such serialization errors (locate the "invalid" Proc objects) for an object (does not have to be AR in general) ?


Usually it's better to store the user id in the session, not the User instance itself. This does mean you have to do a db (or memcache) lookup for authenticated requests, but it saves you a ton of headaches around serialization/caching that you'd otherwise have to deal with.

Also, it's not an "invalid" Proc in some sense. Proc instances are containers for Ruby code and application state and therefore cannot be serialized, ever.


For this specific case, I would say, store only the attributes. ActiveRecord::Base#attributes returns a hash of the attributes stored in the database, so it will almost certainly not contain any Procs.

session[:new_user] = user.attributes unless user.save

In general, however, a simple way is to use inspect on the object you're trying to marshal.

puts obj.inspect

or equivalently

p obj

Usually this will print internal objects, and you can see whether something is a Proc. If you still can't find it and you need to dig deeper, you can inspect all the member variables of the object.

obj.instance_variables.each do |var|
  puts "#{var} = #{obj.instance_eval(var).inspect}"
end


I came across this problem when trying to store an unsaved AR object in the session. Since I was dealing with an arbitrary model, I had to store both the class and attributes in the session so that I could rebuild it later. I solved this by saving the class and attributes in the session together:

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

I could then recreated the object from the session

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜