Sinatra で正規表現を使ったルートを使う場合に注意すること

Sinatra ではルートの設定に正規表現を使うことができる。例えば以下のような感じで。

get %r{/hello/([\w]+)} do |c|
    "Hello, #{c}!"
end
http://www.sinatrarb.com/intro.html
問題

上記の例は公式のページに載っているのだけれど、これをそのまま使おうとしたらハマった。正規表現のルートは暗黙的に 先頭から末尾まで という条件を付加してはくれない、ということ。"^" や、"$" は自分で付加しなければならない。なので例のままだと次のようになる。

% ruby app.rb        
== Sinatra/1.2.6 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.2.11 codename Bat-Shit Crazy)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
192.168.0.1 - - [07/Aug/2011 08:54:04] "GET /hello/sinatra HTTP/1.1" 200 15 0.0019 # 200 Ok 期待通り
192.168.0.1 - - [07/Aug/2011 08:54:19] "GET /aaa/hello/sinatra HTTP/1.1" 200 15 0.0011 # 404 を期待してるのに...
192.168.0.1 - - [07/Aug/2011 08:54:35] "GET /hello/sinatra/zzz HTTP/1.1" 200 15 0.0021 # 同上
192.168.0.1 - - [07/Aug/2011 08:54:52] "GET /aaa/hello/sinatra/zzz HTTP/1.1" 200 15 0.0019 # 同上

ルートにマッチして欲しくないリクエストまでマッチしてしまっている。

解決

適宜 "^" や "$" を付ける。

get %r{^/hello/([\w]+)$} do |c|
    "Hello, #{c}!"
end
% ruby app.rb
== Sinatra/1.2.6 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.2.11 codename Bat-Shit Crazy)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
192.168.0.1 - - [07/Aug/2011 09:17:43] "GET /hello/sinatra HTTP/1.1" 200 15 0.0018 # 200 Ok
192.168.0.1 - - [07/Aug/2011 09:17:50] "GET /aaa/hello/sinatra HTTP/1.1" 404 457 0.0013 # 404 期待通り
192.168.0.1 - - [07/Aug/2011 09:17:58] "GET /hello/sinatra/zzz HTTP/1.1" 404 457 0.0013 # 同上
192.168.0.1 - - [07/Aug/2011 09:18:03] "GET /aaa/hello/sinatra/zzz HTTP/1.1" 404 461 0.0003 # 同上

標準入力のデータをVimで開く

Vim に "-" オプションを付けると、標準入力からのデータを開けるようになる。コレが結構便利だった。

こんなときに便利だった

diff の結果を見る
% git diff | vim -

git diff の結果を今までは less で見ていたけれど、コレだと白黒でわかりづらい。でも、Vim で開けばシンタックスハイライトが有効になり、色付きで表示され差分がわかりやすい。この機能を知らなかった頃 diff の結果を Redmine などのツール上から見ていたり、リダイレクトでファイルに出力させそれを Vim で開いて見ていた。これらはターミナルからブラウザへ移ったり、一旦ファイルに保存したりと、ちょっとひと手間かかっていたけど、それがなくるので便利。

grep の結果を見る
% grep -n hoge **/* | vim -

grep の結果を Vim で開き結果の行にカーソルを合わせて、"gF" コマンドを実行すると、該当ファイルの該当行にジャンプする。また "ctrl+w gF" コマンドだとジャンンプ先を新しいタブで開く。今までは grep した結果をコピペし、新たに vim を立ち上げて開いていたけれど、もうそんなことをする必要はないのかも。ちょっと "ctrl+w gF" と打つのが面倒かもしれないけど (キーバインド?)。

第0回 スタートHaskell 感想

第0回 スタートHaskellに参加した。定員180人のところへ200名以上の参加希望があり、Haskell の人気っぷりがうかがえる。女性もちらほら。Haskellやるとモテるってホントですか?

感想

Haskell山高い!
  • プログラミングHaskell をマスターして、山の 1 合目付近。
  • Real World Haskell をマスターして、山の 2 合目付近。
    • 個人的には、プログラミングHaskellで2合目、RWH で4合目くらいだろうと思っていたので、ちょっとショック。山は高ければ高い程やりがいが出るって、誰かが言ってたっけ。

プログラミングHaskell

プログラミングHaskell

Real World Haskell―実戦で学ぶ関数型言語プログラミング

Real World Haskell―実戦で学ぶ関数型言語プログラミング

Nullがない
  • 今まで気付いていなかったけど、確かに Null がない。
  • Nullがないことによって安全にプログラムを組める?
    • まだ実感というか実践がないのでなんとも言えないが、期待感はある。つくったプログラムを見て、そういえば Null がないねって感じで、自然に組めるのかな。
Debug.Trace
  • 便利そう。
  • スピーカーの Travis さんは Haskell を始めてから 1 年くらいは Debug.Trace を知らなかった。もっと早くに知っていればよかった!と思ったそうだ。
    • それを今回教えてくれた。Thank you.
  • 今回の例では、ガードの判定部分に挟む使い方をしていた。trace は 2 番目の引数を返すので、ガードに挟んで 2 番目の引数に False を渡せば、そのガードの部分が True になることはない。単にデバッグ文を出力して次のガードの判定に移る。
    • trace がこういう使い方しかないのであれば、2 番目の引数は省略してどんなときでも False を返す、という仕様にすればいいのに。そうなっていないということは、他にもいろいろな使い方があるのか。
hoge a | trace ("hoge " ++ show a) False = ... 
LTのレベルが !
  • え、初心者向けじゃないんですか !? ってくらいのレベルの高さ。
  • 全部は理解はできなかったけど、それなりに楽しめた。
  • Haskell は素晴らしいってことで OK ?
型重要 !
  • 重要です。
アプリ, ツールとか

まとめ

面白かった。次も参加したいと思う。平日だと厳しいかなー。

*1:Haskell じゃないけど

No space left on device

問題

gem ライブラリを幾つかまとめて update したところ

No space left on device

というメッセージが表示され、update は失敗した。

調査

メッセージの内容を見る限り HD の容量が足りなくなったのかと思い、df コマンドを打つも、特に異常なし。

% df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/surly-root
                      7.3G  4.7G  2.2G  68% /
none                  114M  180K  114M   1% /dev
none                  121M     0  121M   0% /dev/shm
none                  121M   44K  121M   1% /var/run
none                  121M     0  121M   0% /var/lock
/dev/sda1             228M   21M  196M  10% /boot

調べると、容量だけでなく i-node が一杯になってしまった場合にも、表示されるメッセージということがわかった。 df コマンドに i オプションを付けることで i-node の使用量がわかる。

% df -i 
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/mapper/surly-root
                      482384  482384       0  100% /
none                   29035     671   28364    3% /dev
none                   30816       1   30815    1% /dev/shm
none                   30816      19   30797    1% /var/run
none                   30816       3   30813    1% /var/lock
/dev/sda1             124496     214  124282    1% /boot

満タンです。

解決

いらないファイルを消す。

考察

このマシンでファイルが大幅に増える契機はシステム的なものを除けば、gem のインストールや、github から参考にしたいコードを clone したときが多いと思う。
とりあえず gem のインストール時に no-ri no-doc オプションを付けて、ri や rdoc ファイルが作成されないようにしよう。

no-ri no-doc

~/.gemrc を編集。

gem: --no-ri --no-rdoc

...そんな変らないよな。

Haskell Platform

http://d.hatena.ne.jp/kazu-yamamoto/20110523/1306121040 を読んで、Haskell Platform というパッケージの存在を知った。
今まで個別でインストールしていた Haskell 関連のパッケージを削除して、 Haskell Platform をインストールした。

%sudo apt-get install haskell-platform

Node on Heroku

Heroku の Stacks に新しいバージョンが追加された。まだベータではあるけれど。新しい機能が幾つかあるけれど、その中で一番気になるのは node.js がサポートされるようになったこと(以前より試験的な運用はされていたけど)。

node.jsを使ったアプリの作成方法

基本的に Getting started with Node.js on Heroku/Cedar に書いてある通りでOK。そこでは express を使ったサンプルが書かれている。

ちょっとしたトラブル

ただ、はじめて動かしたときはなぜかうまくいかなかった。うまくいかなかったときの ps コマンドの結果は以下の通り。Command が空欄になってしまっていた。アクセスしても Application Error になる。

% heroku ps
Process       State               Command
------------  ------------------  ------------------------------
web.1         created for 5m  

ログを見てもプロセスが起動されていないことがわかる。

% heroku logs
2011-06-01T12:11:15+00:00 heroku[router]: Error H14 (No web processes running) -> GET high-ice-521.herokuapp.com/    

手順を振り返ってみてもドキュメント通りだった。しかたがないので一旦アプリを破棄し、 heroku (gem) をアップデートした (heroku-2.2.1)。その後もう一度試してみたところ、うまく動くようになった。
原因は何だったのだろう?heroku のバージョンが古かったのか、それとも他の原因なのか...。


追記
バージョンアップする前の heroku のバージョンは 2.0.4 だった。ここには run と scale コマンドを使う場合は、2.1.0 以上のバージョンにしろよとある。この辺りが関係あるのかしらん。

pushState, popState

githubリポジトリディレクトリをたどっていくときのエフェクトが気になったので調べてみた。

戻る・進む

とりわけ気になるのが、アドレスバーの内容は書き変わるけれど、画面の更新は一部しか起こらないこと。しかも、ブラウザの戻る・進むボタンに対しても同様の画面の更新が起きること。どのイベントをキャッチしているのだろう?onload イベントだとすでに画面が切り替わってしまっているので、使われていなさそう。

pushState, popState

githubJavascript のソースを見てみると、pushState というのを使っているということが分った。push とくれば、そう pop。戻る・進むボタンをクリックしたときに popstate イベントが発生する。そのイベントの中で画面更新の処理が走っていた。

サンプル

カレンダーを表示するページを作ってみた => http://hcal.heroku.com/2011/05。動作確認は MacFireFox4 と Chrome11 で行っている。pushState というものの状態は全く保存(push)していないのであまり参考にはならないかも。
ソースを github に置いた。https://github.com/ymmtmsys/pushState-calendar