先日、C言語用単体テストフレームワークであるCutterの新バージョン1.0.6がリリースされました。(アナウンス)
NEWSにも書いてあるように、今回のリリースでも多くの新機能がありますが、ここではその中でも特におすすめの構造体定義なしで複雑なテストデータを使えるAPIを紹介します。
この新機能によりもっと簡単にデータ駆動テストが書けるようになります。実際、milter managerのテストが簡単に書けるようになりました。
データ駆動テストとは同じテストケースに対して複数のテストパターンを適用するテスト手法です。これにより多くのテストパターンを簡単に書くことができるという利点があります。
例えば、入力された文字列の小文字をすべて大文字に変換するto_upper()関数のテストをするとします。テストデータは以下の3つを考えます*1。
これはこのように書けます。
1 2 3 |
cut_assert_equal_string("HELLO", to_upper("hello")); cut_assert_equal_string("HELLO", to_upper("HelLo")); cut_assert_equal_string("HELLO", to_upper("HELLO")); |
データ駆動テストでは、テストケースはこのようになります。
1 |
cut_assert_equal_string(expected, to_upper(input)); |
このうち、expectedとinputを外部から与えることになります。Cutterではこのように書きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
void data_to_upper (void) { #define ADD_DATUM(label, expected, input) \ gcut_add_datum(label, \ "expected", G_TYPE_STRING, expected, \ "input", G_TYPE_STRING, input, \ NULL) ADD_DATUM("all lower", "HELLO", "hello"); ADD_DATUM("mixed", "HELLO", "HelLo"); ADD_DATUM("all upper", "HELLO", "HELLO"); #undef ADD_DATUM } void test_to_upper (gconstpointer data) { const gchar *expected, *input; expected = gcut_data_get_string(data, "expected"); input = gcut_data_get_string(data, "input"); cut_assert_equal_string(expected, to_upper(input)); } |
QtのQtTestLibではこのようになります。 Chapter 2: Data Driven Testingより:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void TestQString::toUpper_data(QtTestTable &t) { t.defineElement("QString", "string"); t.defineElement("QString", "result"); *t.newData("all lower") << "hello" << "HELLO"; *t.newData("mixed") << "Hello" << "HELLO"; *t.newData("all upper") << "HELLO" << "HELLO"; } void TestQString::toUpper() { FETCH(QString, string); FETCH(QString, result); COMPARE(string.toUpper(), result); } |
ほとんど同じくらいの手間で書けているのではないでしょうか。
テストプログラムは重複があってもいいからわかりやすい方がよい、とよく言われます。しかし、そのために、重複がたくさんある中から、興味がある重複していない部分が見つけづらくなるのは問題かもしれません。データ駆動テストでは、どのようにテストしたいのかがわかりやすいテストケースになる傾向がある気がしています。
多くのテスティングフレームワークはデータ駆動テストをサポートしています。PerlのTest::Base、RubyのRSpec*2、C++のQtのQtTestLibやGoogle Testでもサポートされています。他にもまだまだたくさんあります。
テストデータの入力方法も様々で、テストプログラム中でテストデータを生成するものから、データベースからテストデータを取り出すもの、CSV、Excelなどから取り出すものもあります。
動的に複雑なことができるスクリプト言語、アノテーションなどでメタデータを指定できる最近の言語、トリッキーなC++などでは便利にデータ駆動テストを実行できるテスティングフレームワークは多くあります。しかし、C言語用のフレームワークではそんなになかったのではないかと思います。*3
Cutterに興味がある方は使ってみたり、メーリングリストなどで提案、質問などしてみてください。
迷惑メール対策ソフトウェア、milter manager 0.9.0をリリースしました。
変更点にもある通り、前のリリースである0.8.0より処理速度と安定性が向上しています。手元のメールシステムでも安定して動作しており、興味のある方に試してもらえる品質になってきたと思います。
このリリースは1.0.0のリリース候補版という位置付けです。0.9.0に問題が見つからなかった場合は0.9.0が1.0.0としてリリースされます。
最初のリリース時にもらったフィードバック*1を元に0.8.0でいくつか機能を拡張しましたが、今回はmilter manager本体に目立った機能追加はありません。これは、いつまでも完成しない1.0.0を待ってもらうより、まずは安定して動作するmilter managerを提供して、有効に使ってもらう方が有用だろうという判断からです。
いくつか追加機能の案はあるのですが、それは1.0.0のリリース後に実装する予定です。0.9.0のリリースでは組み込みの適用規則の追加と周辺ツールの機能追加にとどめました。
今回は以下の2つの適用規則が追加されました。
sendmail-compatibleは常にmilterを適用するので適用規則ではないのですが、適用規則の枠組みを使った応用例ということで追加しました。
適用規則中ではMTAからmilterに渡されるマクロを参照・変更することができます。この機能をフィルタのように利用しているのがsendmail-compatibleです。
SendmailとPostfixはともにmilter対応しているMTAですが、milterに渡すマクロの実装に互換性がありません。例えば、SendmailとPostfixではマクロ名が異なる、SendmailとPostfixでマクロが渡ってくるタイミングが違う、ということがあります。(詳しくはPostfix before-queue Milterサポートにあります)
この非互換の部分に依存しているmilterはSendmailでは動いてもPostfixでは動かない場合があります。例えば、dnsbl-milterがそのようなmilterです。*2
sendmail-compatibleは、Postfixが渡してきたマクロをSendmailが使っているマクロ名でもアクセスできるようにしたり、ダミーの値を入れたマクロをmilterに渡すなどして、できるだけ非互換の部分を利用しているmilterも動作するようにします。
適用規則の部分はmilter managerの動作の中で、もっとも特徴的で応用範囲が広い部分です。1.0.0リリース後はこれ以外にも応用できるような機能を追加する予定です。
なにかアイディアがあればメーリングリストなどで共有してもらえると、より有用な迷惑メール対策システムを構築できるようになるかもしれません。お待ちしています。
0.9.0ではこれまでよりも速度と安定性が向上していて、実際に試してみることができる品質になっています。milter managerに興味のある方はぜひ試してみてください。もし、問題が見つかった場合はその問題を修正してから1.0.0をリリースします。(問題の修正が大きな変更を伴う場合は既知の問題として修正を先送りする可能性もあります)
機能追加は1.0.0リリース後に行うので、もうしばらくお待ちください。
参考: milter managerのインストールドキュメント
*1 例えばmilter managerを利用したRgrey - モーグルとカバとパウダーの日記。ありがとうございます。
UbuntuやFedoraなど最近のディストリビューションでは、仮想化技術としてXenではなくKVMを採用していますが、CentOS 5.2やDebian GNU/Linux lennyではまだXenがサポートされています。
ここではCentOS 5.2をDom0とし、その上でDomUとしてDebian GNU/Linux lennyをインストールする方法を紹介します。手順をたどっていくと、インストールしたDebianにsshでログインできる状態になります。
インストール後は通常のホストと同様にsshでログインし、使用することができます。
root権限の必要なコマンドは一般ユーザがsudoで行う前提で書いています。sudoの設定を行っていない場合は、suなどでrootユーザになって実行してください。
まず、Xen用のカーネルをインストールし、起動時にXen用カーネルから起動するようにします。
/etc/sysconfig/kernelを編集し、デフォルトのカーネルを変更します。これはXen用カーネルをインストールする前に行う必要があります。
変更前:
DEFAULTKERNEL=kernel
変更後:
DEFAULTKERNEL=kernel-xen
次に、Xen関連パッケージ(Xen用カーネルも含む)をインストールします。
% sudo yum install -y xen
インストールするDebianをCentOSと同じネットワークにおきたい場合はこのまま再起動し、Xen用カーネルで起動してください。このような構成はブリッジモードと呼ばれ、例えば、CentOSのIPアドレスが192.168.1.2でDebian lennyのIPアドレスが192.168.1.3というようなネットワーク構成になります。(参考: 第3回 Xen環境で仮想ネットワークを構築:ITpro)
そうではなく、DebianをCentOSの後ろにあるネットワークに置く場合は設定を変更する必要があります。このようなネットワーク構成のためにNATモードとルーティングモードがあります。違いはDebianが外部ネットワークから見えるか見えないかです。NATモードでは見えませんし、ルーティングモードでは見えます。(参考: Xen Networking - Wiki: 英語ですがネットワーク構成を示した図があります)
ここでは、より安全なNATモードにします。
ネットワーク構成を変更するには/etc/xen/xend-config.sxpを編集します。デフォルトではブリッジモードになっているので、それを無効にして、NATモードにします。
変更前:
... (network-script network-bridge) ... (vif-script vif-bridge) ... #(network-script network-nat) #(vif-script vif-nat) ...
変更後:
... #(network-script network-bridge) ... #(vif-script vif-bridge) ... (network-script network-nat) (vif-script vif-nat)
設定を変更したら再起動し、Xen用カーネルで起動します。
% sudo /sbin/shutdown -r now
起動後、xendサービスが起動し、ネットワークの設定が反映されます。
CentOSにはvirt-installというDomUをセットアップするコマンドがありますが、このコマンドではDebianをインストールできません。Debianをインストールするにはdebootstrapを使います。
Debian関連のファイルは/var/xen/lenny以下に置くことにします。
% sudo mkdir -p /var/xen/lenny
まず、Debian用のファイルシステムとスワップを用意します。ここではディスク容量を10GB、スワップサイズ512MBとしていますが、必要に応じて増やしてください。
% cd /var/xen/lenny % sudo dd if=/dev/zero of=disk.img bs=1M count=10240 % sudo /sbin/mkfs -t ext3 disk.img % sudo dd if=/dev/zero of=swap.img bs=1M count=512 % sudo /sbin/mkswap swap.img
作成したディスクファイルをマウントし、debootstrapでDebianをインストールします。ここではi386のシステムをインストールしています。amd64のシステムをインストールしたい場合は、最後のコマンドの中の「--arch i386」を「--arch amd64」に変更してください。
% cd /tmp % wget http://ftp.de.debian.org/debian/pool/main/d/debootstrap/debootstrap_1.0.10lenny1.tar.gz % tar xvzf debootstrap_1.0.10lenny1.tar.gz % cd debootstrap % sudo make % sudo mount -o loop /var/xen/lenny/disk.img /mnt % sudo su - -c "DEBOOTSTRAP_DIR=$PWD $PWD/debootstrap --arch i386 lenny /mnt http://ftp.jp.debian.org/debian/ $PWD/scripts/debian/sid"
ベースシステムをインストールしたら、chrootし基本的な設定を行います。
% sudo su - -c "/sbin/chroot /mnt"
必要パッケージをインストール:
lenny# apt-key update lenny# aptitude update lenny# aptitude install -V -D -y sudo ssh linux-image-xen-686 lv vim
ホスト名の設定(環境に応じて書き換えること):
lenny# echo 'lenny' > /etc/hostname
/etc/hosts(環境に応じて127.0.1.1の行を書き換えること):
127.0.0.1 localhost 127.0.1.1 lenny.example.com lenny # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts
/etc/fstab:
# /etc/fstab: static file system information. # # <file system> <mount point> <type> <options> <dump> <pass> proc /proc proc defaults 0 0 /dev/sda1 / ext3 defaults,errors=remount-ro 0 1 /dev/sda2 none swap sw 0 0
最後にネットワークの設定です。
ここでは、DebianのIPアドレスとして192.168.1.2を使います。このアドレスは後でXenの設定をするときに使います。
デフォルトゲートウェイはIPアドレスの最後の数字に127を足したものになります。この場合は192.168.1.129になります。
/etc/network/interfaces:
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or # /usr/share/doc/ifupdown/examples for more information. auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.1.2 netmask 255.255.255.0 gateway 192.168.1.129
設定が完了したら、chrootを抜けて、CentOS側にDebianのXen用カーネルを取り出します。
lenny# exit % sudo cp /mnt/boot/{vmlinuz,initrd.img}-2.6.26-1-xen-686 /var/xen/lenny/ % cd /var/xen/lenny % sudo ln -s vmlinuz-2.6.26-1-xen-686 vmlinuz % sudo ln -s initrd.img-2.6.26-1-xen-686 initrd.img
作業が完了したので、Debian用ディスクシステムをアンマウントします。
% sudo umount /mnt
インストールしたDebianをDomUとして登録します。
Debian用の設定は/etc/xen/lenny.cfgに書くことします。以下の設定では、メモリを512MB割り当てています。
/etc/xen/lenny.cfg:
kernel = '/var/xen/lenny/vmlinuz' ramdisk = '/var/xen/lenny/initrd.img' memory = '512' root = '/dev/sda1 ro' disk = ['file:/var/xen/lenny/disk.img,sda1,w', 'file:/var/xen/lenny/swap.img,sda2,w'] name = 'lenny' vif = ['ip=192.168.1.2'] on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'restart' extra = 'xencons=tty clock=jiffies'
vifのipパラメータの値をDebianで指定したIPアドレスと同じ値にすることに注意してください。
また、extraに'xencons=tty clock=jiffies'を設定しているところもポイントです。xencons=ttyをつけないと、起動時に止まってしまうかもしれません。close=jiffiesをつけないと、/var/log/messagesに以下のようなメッセージが大量に出力され、システムが動かなくなってしまうかもしれません。
clocksource/0: Time went backwards: ret=5af6d65a24f delta=-312972075237201 shadow=5af3252f37f offset=3b1338fe
Xenの設定が完了したら試しに起動してみます。
% sudo /usr/sbin/xm create /etc/xen/lenny.cfg -c
ログインプロンプトがでたら成功です。rootユーザのパスワードが設定されていないので、パスワード無しでrootユーザとしてログインできます。
ログインしたら、ユーザを作成し、sudoの設定をします。
lenny# adduser user # ←適切なユーザ名に変えること lenny# visudo
sudoの設定が完了したら、rootのパスワードはロックし、exitします。
lenny# passwd -l lenny# exit
exitすると、またログインプロンプトがでます。Ctrl+]でDebianのコンソールから抜けましょう。ターミナルの幅や高さがおかしくなっている場合はresetコマンドで直るかもしれません。
% reset
この状態でsshでDebianにログインできます。
% ssh 192.168.1.2
後は通常のホストのように運用できます。
CentOSが起動したときにDebianも起動するようにするには/etc/xen/auto/以下にDebianの設定ファイルへのシンボリックリンクを置きます。
% sudo ln -s /etc/xen/lenny.cfg /etc/xen/auto/
CentOSに届いたパケットをDebianに転送し、実際のサービスはDebianが提供する場合はiptablesを使用します。実際のサービスは仮想化された環境上で提供するという使い方です。
以下の内容のXXX.XXX.XXX.XXXの部分をCentOSのIPアドレスに変更し、/etc/sysconfig/iptablesに保存すると、次回起動時からCentOS宛のHTTPとHTTPSのパケットはDebianが処理します。*1
/etc/sysconfig/iptables:
# *nat :PREROUTING ACCEPT [258:20744] :POSTROUTING ACCEPT [18:1152] :OUTPUT ACCEPT [233:17232] # HTTP -A PREROUTING -d XXX.XXX.XXX.XXX -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.2:80 # HTTPS -A PREROUTING -d XXX.XXX.XXX.XXX -p tcp -m tcp --dport 443 -j DNAT --to-destination 192.168.1.2:443 COMMIT
KVMではなくXenを利用した仮想化環境へのDebian GNU/Linux lennyのインストール方法を紹介しました。
CentOS 6ではKVMが利用できるようになっているかもしれませんが、CentOS 5.2がよく使われている現在においてはまだXenを使用する機会も多そうです。CentOSがあるけど実際に使いたいのはDebian系、という場合はCentOS Dom0 + Debian GNU/Linux lenny DomUの組み合わせが使えます。
*1 再起動しなくても「sudo /sbin/service iptables restart」で反映させることができます。
Railsで画像をアップロードするときはどうやっているんでしょうか。
Fleximageというプラグインがあります。よいAPIだと思うのですが、あまり使っている人がいないようなので紹介します。
ここでは1からサンプルRailsアプリケーションを作成しながらFleximageの使い方を紹介します。順番にコマンドを実行・コードを変更していくと動くように書いてあります。
まず、sampleというRailsアプリケーションを作成します。
% cd /tmp % rails sample % cd sample
次に、Fleximageをインストールし、画像用のテーブルを作成します。
% script/plugin install git://github.com/Squeegy/fleximage.git % script/generate scaffold photo title:string image_filename:string image_width:integer image_height:integer % rake db:migrate
以下のカラムは特別なカラムです。Fleximageは以下のカラムが定義されていると、そこに値を設定してくれます。
これらはすべて省略可能です。今回は、せっかくなので、すべて定義しました。
Fleximageを使うため、モデルを以下のように変更します。
app/models/photo.rb:
class Photo < ActiveRecord::Base acts_as_fleximage :image_directory => 'public/images/uploaded' end
これで、アップロードされた画像は"#{RAILS_ROOT}/public/images/uploaded"以下に保存されます。
ここからは、コードを変更し、アプリケーションを動かし、動作を確認しながら進めていきます。そのため、ここでサーバを起動しておきます。
% script/server
http://localhost:3000/photos/にアクセスすると以下のような見慣れたscaffoldの画面になるので、「New Photo」リンクから画像アップロードフォームへ進みます。
scaffoldのフォームでは画像をアップロードできないので、app/views/photos/new.htmlを以下のように変更します。
app/views/photos/new.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<h1>New photo</h1> <% form_for(@photo, :html => {:multipart => true}) do |f| %> <%= f.error_messages %> <p> <%= f.label :title %><br /> <%= f.text_field :title %> </p> <p> <%= f.label :image_file %><br /> <%= f.file_field :image_file %> </p> <p> <%= f.submit 'Create' %> </p> <% end %> <%= link_to 'Back', photos_path %> |
これで、フォームは以下のようになります。
タイトルとアップロードする画像のパスを指定して「Create」ボタンを押します。
画像がアップロードされ、ファイル名やサイズが設定されていることが確認できます。
せっかく画像をアップロードしたので、アップロードした画像も表示するようにします。app/views/photos/show.html.erbに以下を追加します。ここでは、タイトルの下に追加しました。
app/views/photos/show.html.erb:
1 2 3 |
<p> <%= image_tag(photo_path(@photo, :format => "png")) %> </p> |
PNGフォーマットを指定しているので、コントローラ側でPNGフォーマットを受けつけるようにします。
app/controllers/photos_controller.rb:
1 2 3 4 5 6 7 8 9 |
def show @photo = Photo.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render :xml => @photo } format.png # <- 追加 end end |
PNGフォーマットのビューを作ります。ここが、FleximageのAPIのよいところです。
Fleximageを使ったビューは「#{アクション名}.#{フォーマット}.flexi」というファイル名になります。今回の場合だと、「show.png.flexi」になり、以下のような内容になります。
app/views/photos/show.png.flexi:
1 2 3 |
# -*- ruby -*- @photo.operate do |image| end |
これで、http://localhost:3000/photos/1.pngで画像を表示することができるようになりました。画像表示ページは以下のようになります。
画像表示ページではアップロードされた画像をそのまま表示しました。画像一覧ページでは画像のサムネイルを表示することにします。
サムネイル画像はhttp://localhost:3000/photos/1/thumbnail.gifで表示するようにします。そのため、まず、config/routes.rbを変更します。
config/routes.rb:
1 |
map.resources :photos, :member => {:thumbnail => :get} |
これで、thumbnail_photo_pathが使えるようになるので、index.html.erbを書き換えます。
app/views/photos/index.html.erb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<h1>Listing photos</h1> <table> <tr> <th>Title</th> <th>Thumbnail</th> <th colspan="3">Action</th> </tr> <% @photos.each do |photo| %> <tr> <td><%=h photo.title %></td> <td><%= image_tag(thumbnail_photo_path(photo, :format => "gif") %></td> <td><%= link_to 'Show', photo %></td> <td><%= link_to 'Edit', edit_photo_path(photo) %></td> <td><%= link_to 'Destroy', photo, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New photo', new_photo_path %> |
ここでは意味もなくフォーマットにgifを指定していますが、これはFleximageが画像フォーマットを簡単に変更できることを示すためです。
コントローラにGIFフォーマットに対応したthumbnailアクションを定義します。
app/controllers/photos_controller.rb:
1 2 3 4 5 6 7 |
def thumbnail @photo = Photo.find(params[:id]) respond_to do |format| format.gif end end |
サムネイルのGIF画像用のビューは以下のようになります。とてもすっきり書けています。
app/views/photos/thumbnail.gif.flexi:
1 2 3 4 |
# -*- ruby -*- @photo.operate do |image| image.resize('80x60') end |
変更した一覧ページを表示するとこうなります。
アップロードした画像がサムネイルとして表示されています。
すっきりしたAPIのRails用画像アップロードプラグインFleximageを紹介しました。
ここでは触れませんでしたが、Fleximageは機能が豊富でカスタマイズ性にも優れています。例えば、アップロードされた画像を表示するときに影をつけたり、文字を入れたりといろいろ加工することができます。また、ファイルではなく、データベースに画像を保存することもできます。
Fleximageは日本語の情報がほとんどないのが不思議ですね。あまり使われていないのかもしれません。
ImageMagickを使って画像に影をつけるシェルスクリプトです。これを使うと、このページのスクリーンショットについているような影をつけることができます。
add-shadow.sh:
1 2 3 4 5 6 7 8 9 |
#!/bin/sh if [ $# != 2 ]; then echo "Usage: $0 INPUT SHADOWED_OUTPUT" exit 1 fi convert $1 \( +clone -background black -shadow 80x6 \) \ +swap -background none -layers merge +repage $2 |
このように使います。
% ./add-shadow.sh image.png shadowed-image.png
2009/3/24時点でのActiveLdapの最新リリースは1.0.2ですが、ActiveLdap 1.0.2はRails 2.3.2には対応していません。これは、ActiveLdap 1.0.2の方がRails 2.3.2より早くリリースされたからです。基本的に、ActiveLdapはリリース時点での最新のRailsに対応していますが、未来のRailsには対応できていません。
さて、そんなActiveLdapですが、trunkではRails 2.3.2に対応しています。(Issue 18 - ruby-activeldap - [Rails 2.3 Support] :: Running WEBrick Hangs - Google Code)
また、Rails 2.3.2だけではなく、Ruby 1.9.1にも対応しています。(Issue 20 - [Ruby 1.9 Support] :: Running Tests - Google Code) 対応の過程でAlexey.Chebotarさんが、Ruby/LDAPをRuby 1.9.1に対応しました。
Ruby/LDAPはOpenLDAPのRubyバインディングで最終リリースが2006/8/9です。Alexeyさん以外にもRuby 1.9.1対応した成果をフィードバックしている人がいるのですが、まだ対応してもらえていないようです。
Alexeyさんもメンテナの方に連絡をとってみたということですが、まだ対応してもらえていないようです。パッチの形で転がっているよりも、パッチが取り込まれた形の方が利用しやすいということと、AlexeyさんがRuby/LDAPをメンテナンスする意志があるということだったので、ActiveLdapのリポジトリにRuby 1.9.1対応版のRuby/LDAPが入っています。(リポジトリ)Ruby/LDAPをRuby 1.9.1で使いたいという方はこれを使ってみるとよいと思います。
少し脱線しましたが、ActiveLdapのtrunkをRailsアプリケーションで使う方法がActiveLdapプロジェクトのWikiにあります。(UsingTrunkWithRailsJa) Rails 2.3.2でActiveLdapを使いたい場合はこの方法を参考にしてください。
当初は次のリリースは1.1.0と考えていたのですが、1.1.0の前に、Rails 2.3.2に対応している現時点のものを1.0.3をリリースすることも考えています。いくつか予定されていた項目がまだ実現されていないので1.1.0を出すことはできないのですが、その前にRails 2.3.2対応版を出すことには価値があるかもしれないと思うようになってきました。*1
1.1.0に予定されていた項目の1つにドキュメントの整備というものがあります。この項目もまだ実現できていない項目の1つなのですが、現在、id:tashenさんがチュートリアルの日本語訳を行ってくれています。(ありがとうございます!)
ActiveLdapは活発に開発が行われているライブラリなので、RubyでLDAPを便利に操作したい場合はActiveLdapを使うことを検討してみてください。そして、より使いやすく有用なライブラリにするために、バグ修正やドキュメント作成などでプロジェクトに協力してくれる人を募集しています。お待ちしています。
*1 Rails 2.3.2に対応していないというIssueが2つ登録されたりしたので。