ruby-pytstをRubyForgeに登録

Posted by yatsu Mon, 04 Jun 2007 07:00:13 GMT

ruby-pytstのソースが行方不明になっていたので、RubyForgeに登録しました。

RubyForge: ruby-pytst

初めてRubyForgeに登録したのですが、WikiとSVNブラウザがエラーになります。なぜでしょうね?

ruby-pytstは、Wiki文章中のキーワード一括置換のために毎日使用していますが、半年以上、安定動作しています。

以下、READMEを載せておきます。

ruby-pytst

ruby-pytst is a port of pytst to Ruby. It is a implementation of Ternary Search Trie (TST) and it also supports scanning by the Aho-Corasick algorithm. It is built with SWIG.

This software is distributed under LGPL.

I have successfully built on the following environments.

  • (1) Mac OS X 10.4, Ruby 1.8.4 (Fink)
  • (2) Fedora Core 5, Ruby 1.8.4

tst_wrap.cxx in this package was generated on (1) with SWIG 1.3.19.

Author: Masaki Yatsu <yatsu at yatsu.info>

Installation

Generate the Makefile.

% ruby extconf.rb

Make it.

% make

Then, install it as root.

% make install

If you want to generate the Ruby wrapper codes from tst.i by yourself, execute the following at the beginning.

% swig -c++ -ruby -Iinclude tst.i

How to Use

There is no documentation at this point, but there is README.html of pytst in the doc directory.

There are examples in the example directory. You can run examples like this.

% ruby example/tokenize.rb

ruby-pytst supports following character sets.

  • ASCII ($KCODE = ‘NONE’)
  • EUC-JP ($KCODE = ‘EUC’)
  • Shift_JIS ($KCODE = ‘SJIS’)
  • UTF-8 ($KCODE = ‘UTF8’)

You have to specify $KCODE before you create a Pytst::TST.

There is the EUC-JP example in the example directory.

% ruby -Ke example/japanese_euc.rb

The option -Ke means $KCODE = 'EUC'.

See also

pytst:
http://nicolas.lehuen.com/download/pytst/

Ternary Search Trie:
http://en.wikipedia.org/wiki/Ternarysearchtries

Aho-Corasick algorithm:
http://en.wikipedia.org/wiki/Aho-Corasick_algorithm

Posted in ,  | no comments | no trackbacks

Fink: gonzui, bdb-rb

Posted by yatsu Mon, 09 Apr 2007 04:22:08 GMT

gonzuiと、それが使用するbdbライブラリのfinkinfoを作成しました(探しても見つからなかったので……)。

こちらからどうぞ:
http://yatsu.info/finkinfo/

/sw/fink/10.4/local/main/finkinfo ディレクトリに devel, libs/rubymods のようにサブディレクトリを作り、その中に .info ファイルを置いて、fink install します。

% fink install bdb-rb gonzui

gonzuiはdaemonicに対応した方が親切だったかもしれませんが、今回は対応していません。

Posted in , ,  | no comments | no trackbacks

User Engineの中にLord of the Rings発見

Posted by yatsu Sun, 29 Oct 2006 01:21:52 GMT

RailsのUser Engineをいじっていて、Lord of the Ringsのセリフを発見。

if user?
  # ... then if that logged user is NOT authorised...

  unless current_user.authorized?(controller, action)
    # YOU... SHALL... NOT... PASS!

You shall not pass!

ガンダルフかっこいい!

Posted in  | no comments | no trackbacks

RailsでMCImageManger, MCFileManagerを使う

Posted by yatsu Sun, 29 Oct 2006 01:21:30 GMT

JavaScriptで作られたHTMLエディタはいくつかありますが、僕はTinyMCEが好きで、よく使っています。 Railsアプリに組み込むのも簡単で、少しJavaScriptコードをいじるだけで、AjaxでロードしたテキストエリアにTinyMCEを組み込むこともできます。

TinyMCEがさらにすごいのは、MCImageManagerMCFileManagerというプラグインをもっていることです。 MCImageManagerは画像をアップロードすることができ、GDを使ってサムネイルも作ってくれます。 MCFileManagerは想像どおりの機能をもっています。 また、MCImageManagerとMCFileManagerは相互に連携することが可能です。

これらは単にTinyMCEのプラグインというだけでなく、単独でアプリに組み込むこともできるのが素晴らしいです。 どちらも売り物なので買わなければなりませんが、値段は高くないので、充分買う価値はあると思います。

MCImageManagerとMCFileManagerはこのように素晴らしいものですが、PHPで作られているというのがひとつの難点です。 ファイルをアップロードするときはたいていユーザー認証が必要となりますが、組み込み元のアプリがRailsの場合、それを実現するには、PHPからRailsのセッションとユーザー権限を参照しなければなりません。 そのやり方については、TinyMCE Forumに質問されているのを見つけましたが、具体的なやり方は見つかりませんでした。 ということで、ここに僕のやり方を書いておきます。

MCImageManager/MCFileManagerは認証の枠組をもっており、プラグインという形でそれを拡張できるようになっています。 そのため、コードをどこに記述し、どのように拡張するかは問題ではありません。 PHPとRailsでのセッション/権限情報の受け渡しだけが問題となります。

セッション/権限情報の受け渡し方法としては以下の2つの方法が考えられます。

  1. RailsのセッションをDBに保存し、PHPがそのセッション情報と権限を取得し認証する
  2. PHPからRailsにHTTPリクエストを送ってRails側に認証させる

まず1を検討します。 セッション情報をDBに保存するには、config/environment.rb で

config.action_controller.session_store = :active_record_store

とするだけでよいので非常に簡単ですが、セッションに保存されたデータは sessions テーブルの data フィールドに Marshal.dump の結果が格納されます。 セッションが有効かどうかチェックするだけであれば問題ありませんが、セッションからユーザー情報を取得し権限をチェックする必要がある場合、data フィールドの中身を Marshal.load しなければなりません。 PHP自身でそれをやるのは困難ですし、Rubyのスクリプトを作って呼び出そうとすると、Railsのライブラリ群をロードしなければならず(それがないとクラス情報が足りなくてエラーになります)、起動に時間がかかってしまいます。

sessions テーブルにカラムを追加してユーザー情報を取りやすくすることもできないわけではありませんが、ActiveRecordをこのために拡張するのはきれいでないし、実装も面倒です。

1は難しそうなので、2の方法を検討します。 RailsのセッションIDはCookieの _session_id で渡されており、MCImageManager/MCFileManagerを開いたときもこのCookieが渡されるので、PHPからRailsのセッションIDを取得することは可能です。 このセッションIDをCookieにセットして、PHPからRailsへ、ローカルホストのWebサーバーを介してリクエストを送って認証結果を返してもらえばよさそうです。 PHPにはCURLライブラリがあるので、HTTPリクエストを送るのは簡単です。

ということで、2の方法で実装することとします。

Read more...

Posted in ,  | no comments | no trackbacks

LesserWiki + ruby-pytst

Posted by yatsu Sun, 15 Oct 2006 00:27:25 GMT

LesserWikiの自動リンクは今まで正規表現で置換していましたが、ruby-pytstを使うようにしました。 ruby-pytstがインストールされている場合だけ、自動的に使用されます。

1500件のTiddlerがある状態で1つのTiddlerのレンダリングに3秒以上かかっていたのが、1.5秒以下になりました。 いちおう速度は2倍になりましたが、まだまだ遅いです。 自動リンク以外の置換も改善する必要がありそうです。 lesserwiki.orgに置いてあるものはキャッシュが効いているので、この遅さは体感できません :)

ActiveRecordから配列を受け取ってTSTを構築すると遅いので、MySQLアダプタのところから手を入れて、直接TSTを構築するようにしてしまいました。 なのでruby-pytstを使う場合は、MySQLを使わなければなりません(えー)。 これは後でなんとかします。

ちゃんと調べてみると、Railsコンポーネントを使っている部分が非常に遅いことに気づきました。 これからトップページ閲覧時&Tiddler保存時のサイドバーの描画を高速化します。

やれるだけのことをやったら、memcachedにも対応させたいです。

あと、報告いただいているバグも直します、たぶん……。

Posted in ,  | no comments | no trackbacks

ruby-pytst-0.3.1 (bug fix)

Posted by yatsu Sat, 14 Oct 2006 23:45:19 GMT

2007-06-04 追記 ダウンロードはこちら → yatsu.info : ruby-pytstをRubyForgeに登録

ruby-pytstを更新しました。

TSTに入れてあるオブジェクトがGCで開放されてしまうという、重大でしょうもないバグを修正しました……。

今回はバグ修正だけです。

Posted in ,  | no comments | no trackbacks

ruby-pytst-0.3

Posted by yatsu Fri, 13 Oct 2006 22:38:47 GMT

2007-06-04 追記 ダウンロードはこちら → yatsu.info : ruby-pytstをRubyForgeに登録

ruby-pytstを更新し、pytst-1.14に対応させました。

Posted in ,  | no comments | no trackbacks

ruby-pytst-0.2

Posted by yatsu Tue, 10 Oct 2006 05:41:47 GMT

2007-06-04 追記 ダウンロードはこちら → yatsu.info : ruby-pytstをRubyForgeに登録

ruby-pytstを更新しました。

日本語のテキストを正しく扱えるようにしました。 以前のものはマルチバイト文字の途中のバイトから検索がマッチしてしまう問題がありました。

マルチバイト・エンコーディングは組込変数の $KCODE から取得しています。

$KCODEを指定するには、コードの中で

$KCODE = 'e'

とするか、rubyの起動時に ruby -Ke のようにします。

本家のpytstがバージョンアップして1.14になったので、それに合わせた変更もこれからしなければなりません。

Posted in ,  | no comments | no trackbacks

ruby-pytstに至るまで

Posted by yatsu Mon, 09 Oct 2006 02:59:18 GMT

自分でアルゴリズムを書くのが面倒なのと、メンテナンスする時間がなさそうだという理由で、誰かが書いたものにRubyインターフェースをかぶせるという方針にしました。

pytstの他には、ctstがAho-Corasick法の検索をサポートしていて、使えそうでした。 そこで以下を試みました(括弧内は進捗率)。

  1. pytstをCで書き直し、SWIGを使えずRuby拡張を作る (80%)
  2. ctstのコードからSWIGを使わずRuby拡張を作る (80%)
  3. ctstのコードからSWIGを使ってRuby拡張を作る (95%)
  4. pytstのPython依存部分をRubyで書き換え、SWIGを使ったRuby拡張を作る
    • (ruby-pytstとして公開済み)

1はコードを書き換えてしまっているので最初の方針に違反しているし、手間がかかるため途中で諦めました。 この時点ではSWIGを覚えるのが面倒だという気持ちが強かったです。

2は普通にできましたが、途中からSWIGでやってみたくなりました(あれ?)。

3はけっこう苦労しました。 SWIGる(すうぃぐる)のに簡単なコードと難しいコードがあることがわかりました。 Cで書かれていると、クラスとして見せるためにラッパーを書かなければなりません。 そのため、インターフェースとして公開するメソッドが多いと大変です。 また、typedefがいっぱいあったり、構造体と共用体の構成が複雑だったりすると、泣きたくなります。 ctstの場合は、直接Ruby拡張を書いた方が簡単でした。 いちおう動作しているようなので、SWIGインターフェースファイルだけ置いておきます。

結局、pytstの方がわかりやすくて使いやすいと感じたので、もう一度pytstに戻って、4の方法でruby-pytstを実装しました。

RubyでTST+AC法 (ruby-pytst)

Posted in ,  | no comments | no trackbacks

RubyでTST+AC法 (ruby-pytst)

Posted by yatsu Mon, 09 Oct 2006 01:01:25 GMT

2007-06-04 追記 ダウンロードはこちら → yatsu.info : ruby-pytstをRubyForgeに登録

ずっと前に、pytstをRubyに移植中と書きましたが、作りかけのものを公開しておきます。 ファイル読み込み/書き込み以外は動作していると思います。

pytstはもともとSWIGで実装されているのですが、Python依存部分が結構あって、移植はそれなりに大変でした。

これはTernary Search Trie (TST)というデータ構造を実装したRuby拡張です。 Aho-Corasick法(AC法)によるスキャニングもサポートしています。 文章中から複数のキーワードを抽出したり、一括置換したりするのに使えます。 くわしくはpytstのページをご参照ください。

使用例

例1 (example/tokenize.rb)

コード
require 'pytst'

t = Pytst::TST.new

t['1234'] = 'token 1'
t['123456'] = 'token 2'
t['45678'] = 'token 3'
t['5678910'] = 'token 4'

result = t.scan('1234561234567891012345',
                Pytst::TupleListAction.new)
p result
実行
% ruby example/tokenize.rb
結果
[["123456", 6, "token 2"], ["123456", 6, "token 2"],
["78910", -5, nil], ["1234", 4, "token 1"], ["]

ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

例2 (example/callable_action.rb)

コード
require 'pytst'

t = Pytst::TST.new

t['1234'] = '[token 1]'
t['123456'] = '[token 2]'
t['45678'] = '[token 3]'
t['5678910'] = '[token 4]'

mycallback = Proc.new {|key, length, obj|
  if length > 0
    print obj
  else
    print key
  end
}

myresult = Proc.new {
  puts
}

result = t.scan('1234561234567891012345',
                Pytst::CallableAction.new(mycallback, myresult))
実行
% ruby example/callable_action.rb
結果
[token 2][token 2]78910[token 1]5

ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

今後の予定

  • ファイル読み込み/書き込み
  • 例外処理
  • Marshal対応
  • Rubyっぽいインターフェース(ブロック処理など)

そして最終目的は、LesserWikiのレンダリング速度を改善して、サービス(ASP)化して公開することです。 半年くらいサボッてますが、そろそろ再開しようかと……。

Posted in ,  | no comments | no trackbacks

Older posts: 1 2