rubyスクリプトでRewriteMapを書く際の注意点
公開:2003年07月01日参考文献:mod_rewriteモジュール URL 書き換えエンジン(Apache.jp)
RewriteMapは各ユーザーの.htaccess内では定義できない。サーバの設定ファイル内(ふつうhttpd.conf?)で定義する必要がある。
サーバの設定ファイル内で定義したRewriteMapを各ユーザーの.htaccessから使用することはできる。(サーバの設定ファイルで
RewriteOptions inherit
と明示しておく必要は…ないのかな。手元の環境ではコメント化しても受け継がれてるみたい)
たとえば
RewriteMap zot prg:/foo/bar/zot.rb
RewriteRule ([0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}).html ${zot:$1|not_exist}
のようにして使用する。
一行目がRewriteMapの宣言。zotがこのMapにつけた名前で、のちのちこの名前を使って参照される。prg:はMapとして外部プログラムを使いますよ〜、とmod_rewriteに教えるおまじないでそのあとにつづいているのがプログラムのパス。
二行目で実際にzotを呼び出している。形式は${マップ名:引数|デフォルト値}. この場合の$1は正規表現の後方参照。引数は終端に改行文字が追加された形でRewriteMapプログラムに渡される。デフォルト値であるnot_existはRewriteMapがNULLを返した際に使用される。
RewriteMapとして使用するスクリプトには当然実行ビットを立てておく必要がある。
RewriteMapとして動くプログラムは標準入力から引数を受け取り、結果を標準出力に吐き出すフィルタとして動作する。
入出力をバッファリングされるとまずいので、スクリプトの内部で
$stdin.sync = 1 $stdout.sync = 1
のように指定しておく必要がある。
出力は改行文字で終端せよ、ということなので、スクリプトの中で
print "foo.rb?s=#{line}\n"
のようにして指定していたら、改行が二つ出力されて書き換え結果が妙なことになってしまいました。末端の改行文字を削ったら意図どおりに動くようになったのだけれど、
$stdout.puts("foo.rb?s=#{line}")
のように記述しておくのがおそらく一番面倒がないのだと思います。
海外ホスト屋さんにRuby
公開:2003年06月12日久しぶりにstack-style.orgの間借り先であるAletia Hostingのホスティングプランを眺めてみたら、なんと、サポートされる言語の中にRubyが入っているではありませんか。
Rubyのパスは/usr/local/bin/ruby, バージョンは1.6.5 (2001-09-19) [i686-linux]であります。ここは再販なので、同じ系統の別の再販業者のサーバにもRubyがインストールされている可能性あり。
もしかしたら、と思って調べてみたけど、さすがにmod_rubyまではインストールされてませんでした。残念。
R refrain
公開:2003年06月12日 最終更新:2003年07月04日うーん、Pythonは日本ではマイナーだけど本国ではメジャー、ということで「外からやってきたものをいち早く使いこなしている人」になってしまうのかしら。
「Rubyがオタク臭い」と言われるのは関連書籍の層が(ということはそういう教科書を書ける人材の層が)いまいち薄くて、厚い本の次がいきなり256倍本になってしまっていることもあるのかも、と思います。正直256倍本は「オタク臭い」と言われても否定できない。
でも、なぜあえて今一度廃れた256倍スタイルを持ち込んでくるのか、と言うと、それはやはり書く側や売る側からの要請であって、決してRubyのユーザーが256倍スタイルの書籍を望んでいるわけではないと思うのですよ。あれは「真面目に書くと進まないし続かない」「でも時期を逃すと売れなくなるかも」という書き手と売り手の妥協の産物ですよね。
僕はああいう冗談めかした本ではない、ビシッと真面目に決めた中級向けのRuby本が欲しいなあ、といつも思っています。初級向けにはRubyプログラミング入門というとても良い本があるので。
でも教科書って書くのがすごく難しいから、いい本がなかなか出てこなくてもしょうがないのかなあ、とも思うのです。わからない人にわかるように書くというのは確固たる一つの得がたい才能ですよ。
ピッケル本もといウサギ本の出来はどうなのかなあ。それにしてもなぜウサギ。
in R minor
公開:2003年06月12日 最終更新:2003年07月04日「Rubyってオタク臭い言語だよね」というのは単に「Rubyってまだマイナーでユーザー少ないよね」という言説の別の言い方にすぎなくて、一方で「自分はマイナーな言語にコミットする気はない」という立場表明なんだと思ってます。
eRuby雑メモ
公開:2003年06月12日その一。eRubyには二種類ある。Cで書かれていて、コマンドラインから利用できるerubyと、ライブラリとして使える ERb(Tiny eRuby)。今回使ったのはERbの方。erubyもインストールしようとしたのだけど、makeの途中で
gcc -rdynamic eruby_logo.o eruby_main.o liberuby.a -lcrypt -lm -o eruby eruby_main.o: In function `error_pos': /home/shou/WWW/eruby-0.9.4/eruby_main.c(.text+0x18d): undefined reference to `rb_frame_last_func' /home/shou/WWW/eruby-0.9.4/eruby_main.c(.text+0x193): undefined reference to `ruby_sourcefile' /home/shou/WWW/eruby-0.9.4/eruby_main.c(.text+0x1ac): undefined reference to `rb_id2name' ...
というエラーが出て失敗してしまった。何が悪いんだろう。ちなみにFreeBSD 4.3R,ruby1.6.4とeruby-0.9.4という組み合わせです。
その二、ERbLightではeRubyスクリプト内での関数定義ができない。
require 'erb/erbl.rb' str =<<RHTML <% def foo %> <P>foo</P> <% end %> <% foo %> RHTML ERbLight.new(str).run
とかやると、
% ruby foo.rb /usr/local/lib/ruby/site_ruby/1.6/erb/erbl.rb:54:in `eval': (eval):4:in `foo': undefined local variable or method `_erbout' for #<Object:0x8109c88> (NameError)
と言われて失敗してしまう……
サーバいろいろメモ
公開:2003年06月12日ThinkHostではhttpdの生ログをもらえるが、ログはリアルタイムでは更新されず、一日に一回まとめて更新されるだけ。このシステムはちょっとださいんじゃないかな。
POP3とftpをsshでポートフォワーディングするように設定。こんなかんじ。
ssh -C stack-style.org -L 1234:stack-style.org:21 -L 5678:stack-style.org:110
-Lのオプションはローカル側のポート:接続先ホスト:接続先ポートの様に指定する。こうすると
telnet localhost 1234
でstack-style.orgの21番ポートにつながる仕掛け。
わーい、暗号化だーい、安全だーいと喜んでいたら、どうも一定時間シェルに入力がないと接続が切られてしまう模様。調べてみると、シェル(bash)の設定でTMOUTが有効にされていた。
それならと.ssh/configや.bashrcでTMOUT=0と指定してみる。…駄目。.bashrcは読み込まない設定になっている。.ssh/configの設定は後でbashの設定で上書きされちゃうから駄目…なのかな? 確信なし。
じゃあこっちはどうじゃろなーと、今度は.profileで指定してみる。お、有効になった。ふむ。-norcは指定してあるけど-noprofileは指定していないのね……
スクリプト改造感想・PayPalについて
公開:2003年06月12日Web作成用のスクリプトを変えてdbmを使うようにしたら、起動するたびに必要な情報を集めていた前バージョンと比較して10倍くらい速くなってしまいますぃた。使う前はI/OやMarshalのコストがかさんで重くなっちゃうんじゃないかなーなどと思っていたのだけど、気にするほどではなかったなあ。処理がほぼ一瞬で終わるんで非常に快適。マル。
PayPalの認証作業を終え、PayPal経由で送金が可能になる。そろそろ次のサーバ屋さんに挑戦しようかな。それとも前の業者からの返金が確認されてからにしようかな。
PayPalについて。サーバとのやり取りはすべてSSLによって暗号化されている。Personal Accountでは送金は月100$までと言う制限があるが、より上位の契約に移行することによって制限を取り払うことが可能。送金だけではなく、特定のPayPalアカウントに対して請求を行なうこともできる。どちらの場合でも必要な情報は基本的に自分、あるいは相手のE-Mailアドレスと金額だけ。もちろんそのE-MailアドレスはPayPalの口座と連動したものでなければならない。
PayPalの口座の状態はオンラインでいつでも確認できる。課金があった場合にはその口座の持ち主に課金を知らせるメールが送られる。また、課金があってもすぐに口座に連動したカード(あるいは銀行口座/デビットカード)から引き落としがあるわけではなく、``pending''あるいは``unclaimed''状態の課金に対しては転送を拒否することも可能。
おまけ日記
公開:2003年07月05日 最終更新:2007年10月30日くだんのサーバ屋さんは昨日書いたメールの返事すらよこしません。はーん、そうですか。ではよそを当たることにしましょう。
Web製作用Rubyスクリプトを細々といじり中。毎度のことながらスクリプトをいじっている間は日記を書こうとしてもアイディアが思い浮かばなくなるなあ。じゃあってことで更新しなくなると悪循環が進んでますます日記を書かなくなることが目に見えているのでもっさりしつつも書いてますが。
まぁ今回は一から書くんじゃなくて今使っているものを書き直すだけだから、作業が終わるまでにそれほどの時間はかからないと思います。たぶんね。細かく分離してモジュール化してみるとなんかディスプレイで見ていても綺麗で、一人でモニター眺めながらえへーとしたりして。
今日やったこと
公開:2003年06月12日 最終更新:2003年07月04日海外サーバ屋さんに「もう一週間近く経つのに何も反応無いけど、どゆこと?」とメールを出してみる。
何もせずに待っていると気分がダメになってくるので、Web作成用に使っているRubyスクリプトを根本から書き換えることにする。今使っているのはかなーりスパゲッティな代物なので。今回はdbmとか使ってみよう。それに機能をコンパクトなモジュールに分離して見通しを良くしたいな、とも思ったり。
モーダルダイアログ続報
公開:2003年06月12日 最終更新:2003年07月04日VisualuRubyが2月21日に書いたいろいろに対応してくださったようです。リスト付きのモーダルダイアログが作れるようになればeasyPBEMで無茶をやってごまかしていた部分をもっとまともに書けるのでとても嬉しいです。
でも本当はキチンとバグレポートとかしないと駄目なんですよね。ごめんなさい。対応してくださってありがとうございます。
おっと訂正
公開:2003年06月12日3月3日に外部プログラムの起動例として
pid = fork do
Dir::chdir(path)
command = program + option
exec %("#{command}")
end
というのを書いたけど、Cygwin版のRubyではこれじゃ駄目ですね。
command = path + '/' + program + option
exec %("#{command}")
か
command = program + option
exec %("./#{command}")
なら良いはず。
そんでもって過去日記を読み返してみると、2月17日に「eval使うのはこれが初めて」と書いてますけど、1月27日にはもうevalを使ってるんですよね。これが作為でも何でもない天然なんだから我ながら困ったものです。
んー、人柱バージョンがもしかしたら明日くらいに完成する、のかも…(ぼそぼそ)。
外部プログラムを起動する
公開:2003年06月12日すこーしづつ終盤。いよいよeasyPBEMからゲームの実行ファイルを呼び出す部分を書く。最初は
pid = fork do
exec %("C:/Program Files/.../terran.exe")
end
Process.waitpid(pid)
で行けるかなーと思っていたのだが、SMAC/Xはこれではうまく起動できない。Loading画面が表示されてCDチェックまでは行なわれるが、そこから処理が進まずにプロセスは終了してしまう。bashやMS-DOSプロンプトから起動した場合も同じだ。
コマンドプロンプトから起動するのがまずいのかなぁ、と思ってRubyを256倍使うための本 邪道編を読んだりWebで情報を検索したりサンプルを読んだりしながらWin32oleとWindowsスクリプトホストを使ったソースを書いてみる。こういう感じ。
ws = WIN32OLE.new("WScript.shell")
ws.Run %("C:/Program Files/.../terran.exe")
今度はどうだ? と思って実行しても、あれ? やっぱり駄目だ。CDチェックまでは行くのに、何でだろう…?
んーむ、なぜだなぜなんだと頭をひねりつつエクスプローラの画面を眺めていると、easyPBEM.rbと同じディレクトリにAlpha Centauri.Iniという名前のファイルが出来ているのを発見……
本日のお買いもの
公開:2003年06月12日 最終更新:2003年07月04日秋葉原に出かけて
- Rubyを256倍使うための本 無道編/青木峰郎著
- Ruby ライブラリ編/金平雅夫編
- CVSデスクトップリファレンス/Gregor N.Purdy著でびあんぐる監訳田和勝訳
を買ってくる。無道編のテーマはRacc.ライブラリ編はオライリーから出ているRubyデスクトップリファレンスと内容がかぶってるんじゃないかなあ、とちょっと思いました。そうそう、書泉にはProgramming Ruby(鎚本とかピッケル本とか言えば良いのかな?)も置いてありました。
某所でひろせみほの新刊が出たという話を聞いていたのでそれも買おうかなと思っていたのですが、プレビューしてみると絵柄の古い旧作が多かったので今回は取りやめ。やっぱ中身が見れるってーのはいいやね。
帰りに御徒町の多慶屋で食糧品を買い出し。ここはいつ行っても混んでて目が回る。
SWinをいじくる
公開:2003年06月12日昨日のつづき。SWinの機能を眺めてみたのだけど、ダイアログに載ったコントロールに対してメッセージを送る機能はまだ実装されていないみたい。ふーむ、もしかしたら自分で何とかできないかしらんと押し入れの中からむかーし買ったWindowsプログラミングの本を引っ張り出して眺めてみる。
…ふむふむ、SendDlgItemMessageという関数があるなあ。これを呼び出すラッパーを書いてやればどうだろう。VisualuRuby計画からSWinのソースコードを取ってきて、swin.cやswindialog.cとしばしにらめっこ。…こうかな?
swindialog.cに追加:
typedef LRESULT (WINAPI *DLGMSGPROC)(HWND,UINT,UINT,WPARAM,LPARAM);
VALUE
swindlg_messagingcore(
DLGMSGPROC messaging,
VALUE obj, VALUE itemid, VALUE msg, VALUE wparam, VALU
E lparam){
struct SwinDialog *sd;
unsigned long r,lp;
Data_Get_Struct(obj, struct SwinDialog, sd);
/* SWIN_WINEXISTCHECK(sd->sw);*/
switch(TYPE(lparam)){
case T_FIXNUM:
lp=NUM2UINT(lparam);
break;
case T_STRING:
lp=(unsigned long)STR2CSTR(lparam);
break;
default:
lp=0;
break;
}
r=(*messaging)((HWND)sd->sw.hWnd,NUM2UINT(itemid),(UINT)NUM2UINT(msg),
(WPARAM)NUM2UINT(wparam),(LPARAM)lp);
return INT2NUM(r);
}
static VALUE
swindlg_sendmessage(VALUE obj,VALUE itemid,VALUE msg,VALUE wparam,VALUE lparam
){
return swindlg_messagingcore((DLGMSGPROC)SendDlgItemMessage,obj,itemid
,msg,wparam,lparam);
}
void
Init_swinDialog(){
...
rb_define_method(cSwinDialog, "sendItemMessage",swindlg_sendmessage,4)
;
}
…… モーダルダイアログの作り方
公開:2003年06月12日がよくわかりません。VisulauRubyのサンプル集の中のmdlgtest.rbを参考に色々やってみたのだけど、VRLocalScreen.modalformというメソッドは現時点では使えないのかなあ。これが使えれば一番便利そうなのだけど。
DialogTemplateの使い方はなんとなく分かるのだけど、一度テンプレートに格納したコントロールに対して操作を行ないたい場合(例えば、
tp.addDlgControl(VRListbox, "", ...)
で追加したリストボックスに値をセットしたり、値を取得したりしたい場合)はどうしたら良いのでしょう。SWinのメソッドを直接叩かなきゃ駄目なのかな?
それじゃあアリもんで何とかごまかしてみようかなと思って、こないだのParentDialogにちょこちょこと手を加えてみる。
module ParentDialog
def disable_myself
self.style |= WStyle::WS_DISABLED
end
def enable_myself
self.style ^= WStyle::WS_DISABLED
end
def show_dialog(dlgname, objtype, &init_proc)
if eval "@#{dlgname}"
begin
eval "@#{dlgname}.show"
rescue SWin::WindowNotExistError
create_childdialog(dlgname, objtype, &init_proc)
retry
end
else
create_childdialog(dlgname, objtype, &init_proc)
eval "@#{dlgname}.show"
end
end
def create_childdialog(dlgname, objtype, &init_proc)
eval("@#{dlgname} = VRLocalScreen.newform(self, nil, #{objtype})")
eval("def @#{dlgname}.name;" +
"'#{dlgname}';" +
"end"
)
eval("@#{dlgname}.extend VRDestroySensitive")
eval(%!@#{dlgname}.send_parent("self", "destroy")!)
eval(%!@#{dlgname}.send_parent("OK", "clicked")!)
eval(%!@#{dlgname}.send_parent("cancel", "clicked")!)
if not type::method_defined?("#{dlgname}_self_destroy")
instance_eval("def #{dlgname}_self_destroy;" +
"@#{dlgname} = nil;" +
"end"
)
end
if not type::method_defined?("#{dlgname}_cancel_clicked")
instance_eval("def #{dlgname}_cancel_clicked;" +
"@#{dlgname}.close;" +
"end"
)
end
eval("@#{dlgname}.create")
init_proc.call if init_proc
end
end
子ダイアログの生成時にdisable_myself、破壊時にenable_myselfを呼び出すことで親を無効/有効化し、モーダルっぽい動作をでっちあげるという、なんというかその…。後ろ向きに生きててスミマセン。
