前田です。

中村暁史 <anakamur / exa.i-tech.co.jp> writes:

> MarshalってdelphiのTWriterおよびTReaderを強力にしたような奴
> だと思って、イイのですよね?
> delphiの(デフォの)だと専用バイナリフォーマットでしか出し入れしない
> みたいだ、という意味で。

TWriter/TReaderって何でしたっけ。

> 永続化するかどうかの制御はどーすんのかな?と説明書を読みます…読みます…
> Marshalに読み書きさせたくない属性を自分のobjectに持たせたいと思ったら、
> その属性をdataとかのMarshal非対応オブジェクトにすればいい、って
> ことでしょうか?

RubyにはJavaのtransientみたいなものはないので、そういう時には_dump/_load
を自前で定義してやらないといけません。

class Person
  attr_reader :name, :age
  attr_accessor :nickname
  
  def initialize(name, age)
    @name = name
    @age = age
    @nickname = nil
  end

  # Personを文字列化するためのメソッド
  def _dump(limit)
    # @name, @ageのみ保存
    return Marshal::dump([@name, @age], limit)
  end

  # 文字列からPersonオブジェクトを復元するメソッド  
  def Person._load(str)
    # loadしたデータを引数にしてコンストラクタを起動
    return new(*Marshal::load(str))
  end
end

mick = Person.new("Michael", 23)
mick.nickname = "Mick"
p mick.name     #=> "Michael"
p mick.age      #=> 23
p mick.nickname #=> "Mick"
s = Marshal::dump(mick)
person = Marshal::load(s)
p person.name     #=> "Michael"
p person.age      #=> 23
p person.nickname #=> nil

上の例でPersonは@name,@age,@nicknameというインスタンス変数を持ちますが、
marshalingした時に@nicknameは保存されないようにしてあります。

しかし、実際にこれをruby 1.3.1(99/02/10)で実行すると落ちます:-(
どうやらバグみたいなので別メールでパッチを送ります。

class Person
  transient :nickname
  ...
end

みたいに保存しないインスタンス変数を指定できると便利かもしれませんね。

-- 
前田 修吾 (mailto:shugo / netlab.co.jp)