initialize
一般に、オブジェクトのインスタンス変数 (デフォルトの Yaml シリアライゼーションが格納するもの) と へのパラメーターの間に対応関係がないため、Yaml からのオブジェクトのデシリアライズでは、メソッドは使用されませんinitialize
。
initialize
例として、次のようなを持つオブジェクトを考えてみましょう(他のインスタンス変数はありません)。
def initialize(param_one, param_two)
@a_variable = some_calculation(param_one, param_two)
end
this のインスタンスが逆シリアル化されると、Yaml プロセッサには の値があります@a_variable
が、initialize
メソッドには2 つのパラメータが必要なため、呼び出すことができません。インスタンス変数の数がパラメーターの数と一致してinitialize
いても、それらが対応しているとは限りません。また、一致したとしても、プロセッサーはそれらが渡されるべき順序を知りませんinitialize
。
Ruby オブジェクトを Yaml にシリアライズおよびデシリアライズするデフォルトのプロセスは、シリアライズ中にすべてのインスタンス変数を (名前とともに) 書き出し、デシリアライズ時にクラスの新しいインスタンスを割り当て、この新しいインスタンスに同じインスタンス変数を設定するだけです。
もちろん、このプロセスをより細かく制御する必要がある場合もあります。Psych Yaml プロセッサ (Ruby 1.9.3 のデフォルト) を使用している場合は、必要に応じて (シリアル化のencode_with
場合) またはinit_with
(逆シリアル化の場合) メソッドを実装する必要があります。
シリアル化の場合、Psych はencode_with
、オブジェクトが存在する場合はそのメソッドを呼び出し、 object を渡しcoder
ます。このオブジェクトを使用すると、オブジェクトを Yaml で表現する方法を指定できます。通常は、オブジェクトをハッシュのように扱います。
デシリアライゼーションの場合、Psych はinit_with
、オブジェクトにメソッドが存在する場合、上記の既定の手順を使用する代わりに、再度coder
オブジェクトを渡してメソッドを呼び出します。今回はcoder
、Yaml でのオブジェクト表現に関する情報が含まれます。
両方のメソッドを提供する必要はありません。必要に応じて、どちらか一方のみを提供できます。両方を指定すると、coder
渡されるオブジェクトは、メソッドの実行後にinit_with
渡されるオブジェクトと基本的に同じになります。encode_with
例として、(大規模な計算を回避するための最適化として) 他のインスタンス変数から計算されるいくつかのインスタンス変数を持つが、Yaml にシリアル化されるべきではないオブジェクトを考えてみましょう。
class Foo
def initialize(first, second)
@first = first
@second = second
@calculated = expensive_calculation(@first, @second)
end
def encode_with(coder)
# @calculated shouldn’t be serialized, so we just add the other two.
# We could provide different names to use in the Yaml here if we
# wanted (as long as the same names are used in init_with).
coder['first'] = @first
coder['second'] = @second
end
def init_with(coder)
# The Yaml only contains values for @first and @second, we need to
# recalculate @calculated so the object is valid.
@first = coder['first']
@second = coder['second']
@calculated = expensive_calculation(@first, @second)
end
# The expensive calculation
def expensive_calculation(a, b)
...
end
end
このクラスのインスタンスを Yaml にダンプすると、calculated
値なしで次のようになります。
--- !ruby/object:Foo
first: 1
second: 2
この Yaml を Ruby にロードし直すと、作成されたオブジェクトに@calculated
インスタンス変数が設定されます。
必要に応じて 内から呼び出すこともできますが、クラスの新しいインスタンスを初期化することと、既存のインスタンスを Yaml から逆シリアル化することを明確に区別した方がよいと思います。代わりに、両方から呼び出すことができるメソッドに共通のロジックを抽出することをお勧めします。initialize
init_with