メタプログラミング系のrdocコメントを記述する方法と、その注意点
Rubyの得意技の一つに、メソッドを定義するクラスメソッドを使用したメタプログラミングがあります。しかし、これを利用して作ったメソッドはrdocに表示されないという問題があります。
このような場合、##によるメタプログラミング指示と、:method:/:singleton-method:ディレクティブを使用することでrdocコメントを定義することができます。*1
rdoc自体のrdocには書かれているのですが、日本語の解説が見当たらなかったのでまとめてみました。
インスタンスメソッドを定義するメソッドの場合
## # 説明 define_instance_method :method_name
メタプログラミングによるメソッド定義も、通常のメソッド定義と同様に直前に説明を記述します。唯一の違いは、説明の前の行に「##」を入れることだけです。
上記の場合、define_meta_methodの第一引数である「method_name」というインスタンスメソッドが定義されたものだと判断されます。
メソッド名が引数から判断できない場合
## # :method: instance_method # 説明 define_instance_method :method_name_prefix
第一引数がメソッド名ではない場合などは、:method:ディレクティブを使用することでメソッド名を指定できます。
上記の場合、明示的にメソッド名を指定しているので、「instance_method」というインスタンスメソッドが定義されたものだと判断されます。
クラスメソッドを定義するメソッドの場合
## # :singleton-method: # 説明 define_class_method :method_name
デフォルトではインスタンスメソッドだと判断されますが、クラスメソッドを定義したい場合、:singleton-method:ディレクティブを使用します。また、この場合にも上記と同様にメソッド名を指定することができます。
上記の場合、「method_name」というクラスメソッドが定義されたものだと判断されます。
複数のメソッドを定義するメソッドの場合
一つのメソッドで複数のメソッドを定義する場合*2、上記の方法では数が合わなくなってしまいます。その場合、以下のように空行を利用して定義します。
## # :method: hidden_instance_method # 説明 ## # :singleton-method: hidden_class_method # 説明 ##
もちろんメソッド名の指定もできますし、:singleton-method:でクラスメソッド指定をすることもできます。
上記の場合、「hidden_instance_method」というインスタンスメソッドと、「hidden_class_method」というクラスメソッドが定義されたものだと判断されます。
また、最後の行で「##」と記述していますが、最後のディレクティブが空行の場合には無視されてしまうようなので最後でなくするために何か入れているだけです。「#--」等のコメントでも構わないようです。
アクセス制限が指定されている場合
## # :method: private_hidden_instance_method # 説明 private ## # :singleton-method: protected_hidden_class_method # 説明 protected ##
空行ではなくメソッドの直前にコメントが書かれている場合には、正しく現在のアクセス制限で定義されるようなのですが、空行の場合にはそれがおかしくなってしまうようです。
その場合、空行とコメント行の間にアクセス制限メソッドを置くと正しく動作するようです。ただし、クラスメソッドの場合でも「private_class_method/protected_class_method」ではなく、インスタンスメソッド用の「private/protected/public」を使う必要があるようです。
上記の場合、「private_hidden_instance_method」というprivateなインスタンスメソッドと、「protected_hidden_class_method」というprotectedなクラスメソッドが定義されたものだと判断されます。
引数を指定する場合
引数を指定する場合、メソッド名指定に引数を入れても正しく処理できないようなので、:call-seq:ディレクティブと併用する必要があるようです。