Marshal dump and ActiveRecord store
yanina-mosilevich opened this issue · 2 comments
we use ActiveRecord store similar to that one from docs
class ExchangeRate < ApplicationRecord
def self.get_rate(from_iso_code, to_iso_code)
rate = find_by(from: from_iso_code, to: to_iso_code)
rate&.rate
end
def self.add_rate(from_iso_code, to_iso_code, rate)
exrate = find_or_initialize_by(from: from_iso_code, to: to_iso_code)
exrate.rate = rate
exrate.save!
end
def self.each_rate
return find_each unless block_given?
find_each do |rate|
yield rate.from, rate.to, rate.rate
end
end
end
# in initializer
Money.default_bank = Money::Bank::VariableExchange.new('ExchangeRate')
# when you try to dump money object it raises an error:
Marshal.dump(Money.zero('USD')) # => undefined method `marshal_dump' for ExchangeRate:Class (NoMethodError)
As I see here, custom store needs to implement method marshal_dump.
but even if we try to do it in this case - marshal_load (here) tries to instantiate store object.
So it looks like with current implementation you can't use any class as store, just instance of class. Need to update the docs or re-work current approach of dumping store?
Running into the same issue. The default initializer for the Exchange takes MemoryStore.new (an instance of memory store) but the docs show passing the ExchangeRate class (not an instance). The result is that marshal_dump is undefined because you cant marshal the class object.
I was able to get it working with
def self.marshal_dump
[ExchangeRate]
end
Added to the implementation
@JoshReedSchramm in this case it breaks loading:
Marshal.load Marshal.dump(Money.zero('USD')) # => instance of Class needs to have method `marshal_load' (TypeError)
By default you can marshal the class object, but not in case when you override marshal_dump method.
Compare:
class A; end
Marshal.load(Marshal.dump(A)) # => A
vs
class A
def self.marshal_dump
[A]
end
end
Marshal.load(Marshal.dump(A)) # => instance of Class needs to have method `marshal_load' (TypeError)
In my case I added such temporary fix:
class ExchangeStore
delegate :get_rate, :add_rate, :each_rate, :transaction, to: :ExchangeRate
def marshal_dump
[self.class]
end
end
Money.default_bank = Money::Bank::VariableExchange.new(ExchangeStore.new)
but ideally it should be fixed in Money gem.