Search code examples
rubyserializationactiverecord

ActiveRecord serialize coder argument not seeming to work


I have an Entry class that has a Charge attribute that I want to instantiate from a string as a Charge object when read from the DB:

class Entry < ActiveRecord::Base
  serialize :charge, Charge
end

class Charge
  # Reading from the db as a string
  def self.load(str)
    str.nil? ? nil : new(str)
  end

  # Writing to the db as a string
  def self.dump(chg)
    chg.nil? ? nil : chg.to_s
  end
end

This works fine:

ent = Entry.find(1)
ent.charge.class => Charge

However, AR is issuing a deprecation warning:

DEPRECATION WARNING: Passing the coder as positional argument is deprecated and will be removed in Rails 7.2. Please pass the coder as a keyword argument:

serialize :charge, coder: Byr::Charge

But when I do this, AR fails to deserialize the attribute as a Charge but just returns it as a String from the DB.

class Entry < ActiveRecord::Base
  serialize :charge, coder: Charge
end
ent = Entry.find(1)
ent.charge.class => String

Am I missing something, or is anyone else seeing this?


Solution

  • To ensure that the serialized attribute charge is of the Charge class, you need to specify the :type parameter in the serializer call. Also, the load method should return a new empty object when nil.

    The change in the method signature allows you to define separate coder and type classes. This way, your code can load/dump with a certain class and have the attribute be of a different class.

    class Entry < ActiveRecord::Base
      serialize :charge, coder: Charge, type: Charge
    end
    
    class Charge
      def self.load(str)
        str.nil? ? new(nil) : new(str)
      end
    end
    

    For more information, see: