SyntaxHighlighter

2011年11月6日日曜日

Redmine プラグイン

Redmine プラグイン

以前に Redmine プラグインの練習として作ってみたWiki GChart Formula Pluginの紹介をかねて、Redmine プラグインについて書きます。

オープンクラス

Redmine, Rails に限った話ではありませんが、Ruby のクラスは、オープンです。

Redmine や Rails のプラグインは、このオープンクラスの仕組みをうまく使っているので、今回はその説明を書くことにします。

「クラスがオープンである」というのは、例えば、一度クラスを定義した後からでも、自由にメソッドの追加や上書きなどができるということです。

例として、以下のような Ruby のプログラムを考えます。Testクラスが二回定義されていることに注意してください。

このスクリプトを実行すると以下のように出力されます。

old
new
ok

この例では、(1) で定義したメソッドprintが (4) で再定義され上書きされます。また、(5) で新しいメソッドprint2が新規に追加されています。

C# の部分クラス定義との違い

これは、C# の部分クラス定義の機能を使って、複数ファイルでクラスの各メソッドを定義できることと似た部分があります。

しかし、Ruby ではクラスの定義自体も通常のメソッド呼び出しなどと同じように実行時に行われる点が大きく違います。

C# などでは、定義自体が分割されていようがなかろうが、クラスの定義自体はコンパイル時に解釈され、実行時にクラスのメソッドが途中で動的に追加されたり置き換わったりすることはありません。

そのため、C# でもともと提供されている既存のクラスに対してメソッドを追加するようなことはできません。 また、(1), (4) のように同名のメソッドを定義することもできません。 というか、後から定義した方で上書きできたとしても、実行時にはその片方の定義しか使われないので、意味がありません。

一方で、Ruby ではそれらが可能です。

そのため、上に書いたコードは以下のように動きます。

  • (2) の段階では、まだ (4) の再定義がされていないので、(1) で定義された通りoldが出力されます。
  • (3) の段階では、まだ (5) の定義がされていないので、print2などというメソッドは存在せず、エラーになります。
  • (6) の段階では、(4) の再定義の後なので、newが出力されます。(1) で定義されていた、古いprintメソッドを呼ぶ方法はありません。
  • (7) の段階では、(5) の定義の後なので、okが出力されます。

このように、クラス定義も実行時に行われ、かつクラスがオープンであるために、後から既存クラスの挙動を変更することが非常に柔軟に行えます。

これらの挙動を利用することで、Redmine や Rails では、プラグイン側から Redmine や Rails のクラスを上書きすることにより、自由なカスタマイズをすることができます。

続く。

0 件のコメント:

コメントを投稿