特異メソッドを追加したHashのインスタンスをMarshalでdump,loadしようとしているが,うまくいかなくて,困ってる.
Marshal.dumpでHashのインスタンスをdumpできる.
def set_foo(obj) class << obj def foo "foo" end end obj end p Marshal.dump({ :a => 'aaaaa'}) #=> "\004\b{\006:\006a\"\naaaaa"
特異メソッドを定義してみる.
def set_foo(obj) class << obj def foo "foo" end end obj end puts set_foo({ :a => 'aaaaa'}).foo # => foo
できた.
特異メソッドを定義したオブジェクトはdumpできないので,これをdumpしようとすると,例外が起きる.
def set_foo(obj) class << obj def foo "foo" end end obj end p Marshal.dump(set_foo({ :a => 'aaaaa'})) #=> `dump': singleton can't be dumped (TypeError)
特異メソッドで,marshal_dumpを定義するとdumpできるようになるが,なにもせずにdumpした場合と異なる結果になってしまう.
def set_foo(obj) class << obj def foo "foo" end def marshal_dump dup end end obj end p Marshal.dump(set_foo({ :a => 'aaaaa'})) #=> "\004\bU:\tHash{\006:\006a\"\naaaaa"
先頭に,:\tHash という文字列が加わってる.
このdumpしたのをMarshal.loadしようとすると,Hashクラスのmarshal_loadを呼ぼうとするが,定義してないので,動かない.
def set_foo(obj) class << obj def foo "foo" end def marshal_dump dup end end obj end p Marshal.load(Marshal.dump(set_foo({ :a => 'aaaaa'}))) #=> instance of Hash needs to have method `marshal_load' (TypeError)
Hashクラスにmarshal_loadを定義すると,loadできるようになるが,こんなところを書き換えてると,思わぬところで副作用がありそう.
class Hash def marshal_load(obj) self.update(obj) end end def set_foo(obj) class << obj def foo "foo" end def marshal_dump dup end end obj end p Marshal.load(Marshal.dump(set_foo({ :a => 'aaaaa'}))) #=> {:a=>"aaaaa"}
gem memcache-clientがmemcachedにオブジェクトを保存するときに,Marshal.dumpでシリアライズしていて,このように特異メソッドを定義しているオブジェクトをキャッシュすることができない.困った.