Techioz Blog

ActiveRecord のシリアル化コーダー引数が機能していないようです

概要

DB から読み取られるときに文字列から Charge オブジェクトとしてインスタンス化したい Charge 属性を持つ Entry クラスがあります。

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

これはうまくいきます:

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

ただし、AR は非推奨の警告を発行しています。

しかし、これを行うと、AR は属性を Charge として逆シリアル化できず、DB から文字列として返すだけです。

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

私が何かを見逃しているのでしょうか、それとも他の誰かがこれを見ているのでしょうか?

解決策

シリアル化された属性 Charge が Charge クラスのものであることを確認するには、シリアライザー呼び出しで :type パラメーターを指定する必要があります。また、load メソッドは nil の場合に新しい空のオブジェクトを返す必要があります。

メソッド シグネチャの変更により、コーダー クラスと型クラスを個別に定義できるようになります。このようにして、コードを特定のクラスでロード/ダンプし、属性を別のクラスにすることができます。

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

詳細については、以下を参照してください。