1年半くらい前にRackの構造を調べたときに「Rackは棚ではなく、マトリョーシカである」ということを理解しまして、次のような記事を書いたのです。

マトリョーシカはRackだけのものじゃない、あなたのRubyにもマトリョーシカを!

で、そのときに書いたコードを手直しして「なんでもGem化プロジェクト1」に則ってこの度Gem化しましたので、お知らせいたします。まあ、また小石(tiny gem)を一つ増やしただけですが。

matreska | RubyGems.org | your community gem host

melborne/matreska

Matreskaとは

Matreskaは分かりやすくいえば、「Rackでmiddlewareを連鎖的にcallする仕組みを汎用化したもの」です。つまり「アダプタブルなマルチフィルターのバンドラー(結束具)」ですw。Rackにおけるappに相当するものをMatreskaではcore(芯ですね)といい、middlewareに相当するものをdollまたはfigureといいます。マトリョーシカの正しいスペルはMatryoshkaですが、同名のGemが既に存在していたためそのロシア語らしきmatrëškaから命名しました。

Alt title noshadow

正直何に使えるのか作った本人もまだ良くわかってませんが、基本的には次の二通りの使い方ができます。

  1. 一つの入力に対してアダプタブルなフィルタにより多段的な処理を施す。

  2. 通過させる各フィルタにおいて副産物を生成する。

コードは60行ほどなのでここに貼っておきます。

使い方のサンプル

演算フィルタ

いくつかの例を見てみます。まずはcoreに対しいくつかの演算を施すdollを使った簡単な例を示します。

最初にMatreska.buildでMatreskaインスタンスを生成してcoreをセットします。coreはRackにおけるappと同じようなcallメソッドに応答するオブジェクトです。ここではcoreは実行時(callの呼び出し)に渡される値をそのまま返すものとして実装しています。

dollはRackにおけるmiddlewareと同じようにcoreを引数に取りcallメソッドを持ったクラスです。Matreska.doll(または.figure)はこのdollを簡単に生成するためのショートカットツールです。ブロックの第1引数でcoreまたは前段のdollをcallした結果を取ることができます。そして、Matreska#setでdollをMatreskaインスタンスにセットし、Matreska#callすることで、coreに複数のdollフィルタを適用した結果が得られます。

Rackを知っていれば理解は簡単だと思いますが、注意点はdollにおけるcall呼び出しの順序がRackとは逆である点です。Matreskaでは先にセットされたdollのcallが先に呼ばれる仕様になっています。

多言語翻訳

次の例は、各翻訳用dollで入力ワードを多言語翻訳する例です。

翻訳の結果を各dollにおける副作用として得ています。例ではcallメソッドを持たないArrayをcoreとしていますが、このような場合MatreskaではこのオブジェクトをProcでラップしてcallできるようにします。

コマ送り画像の生成

もう少しマシな例を。GvizとコラボさせてアニメーションGIFの元画像を作る例を示します。GvizではGviz#saveでdotファイルを生成できるので、線画を書き足しつつこれを各dollクラスで実行するようにします。

生成したdotファイルからpngを生成し、RMagickを使ってアニメーションGIFにします。