palkan/store_attribute

TypeError: no _dump_data is defined for class Proc with default proc value

AlexanderShvaykin opened this issue · 1 comments

Hello!
Found problems when caching the object, inside it is calls Marshal.dump(obj)
The problem occurs when the model has a default with proc
Here's my case

class Course < ApplicationRecord
  store_attribute :settings, :foo, :json, default: {}
end

c1 = Course.find(1)
c2 = Course.find(2)
c1.foo[:test] = 2
# Bad
c1.foo #=> {:test=>2}
c2.foo #=> {:test=>2}

class Course < ApplicationRecord
  store_attribute :settings, :foo, :json, default: -> { {} }
end

c1 = Course.find(1)
c2 = Course.find(2)
c1.foo[:test] = 2
# Good
c1.foo #=> {:test=>2}
c2.foo #=> {}

# But!
Marshal.dump(c1) #=> TypeError: no _dump_data is defined for class Proc

# However no problems with ActiveRecord attribute
class Course < ApplicationRecord
  attribute :foo, :json, default: -> { {} }
end

c1 = Course.find(1)
c1.foo #=> {}
Marshal.dump(c1) #=> "\x04\bo:\vCourse\x0F:\x10@attributeso:\x1EActiveModel::AttributeSet\...

Any ideas how to fix this?

I tnink, the right way to deal with it is to implement custom #marshal_dump and #marshal_load for the class: https://ruby-doc.org/core-2.6.3/Marshal.html#module-Marshal-label-marshal_dump+and+marshal_load

It's surprising that AR tries to dump internal metadata, the dump is gonna be huge. I'd suggest considering a different encoding/decoding way, e.g., GlobalID.