iJunku
iCookpadが便利そうだったので、それをパクって参考にして、iPhone向けのジュンク堂検索のサイトを作ってみました。
とりあえずキーワード検索とISBN検索とTwitterへのリンクをつけました。ページ送りは今のところ必要なさそうなので作ってません。そのうち必要になったら作る。ISBN検索で、ISBNを入力したら詳細画面に一発で飛ぶのが便利かも。
ソースはgithubに置いたので、興味のある方はどうぞ。
http://github.com/takahashim/iJunku/tree/master
内容に関していえば、iCookpadと比べれば明らかなのですが、特筆するべきはscrapingが大変な感じになっているところ、でしょうか。もうちょっとDOMのオペレーションに慣れればシンプルにはなりそうですが(あきらめて文字列処理にしているところが大なので)、それでもiCookpadと比べれば簡単にはなりそうもありません。これは元のサイトがテーブルレイアウトなので、classやid属性を使った指定が使えないのが大きいです。
SinatraをCGIでもThin等のアプリサーバでも使えるようにする書き方
個人的にSinatraとLimonadeがマイブームなのですが、Sinatraに関して言えば、CGIで動かす方法は(本家のドキュメントとかでは)あまりフォローされていないようです。国内ではそれなりに記事もあるようなのですが、結局ソースに手を入れてしまう(Sinatraのソースに「Rack::Handler::CGI.run」をベタに書く)か、rackupで実行する方法かが多そう。でも、前者はCGI専用になってしまうのでいまいちだし、後者はシェルが2個実行されるのがどうにも美しくありません(現実的にはあまり問題にならないのかもしれませんが)。
そこでいろいろいじってみたところ、何とか良さげな方法ができました。
まずSinatraのソース。適当です。
require 'rubygems' require 'sinatra' set :run, true get '/?' do "hello" end get '/test' do "hello" end
ポイントは、getの引数の「'/?'」です。普通は「'/'」と書くところですが、CGIで下記のrewriteを使うと、引数が「''」しかマッチングしなくなります。そこで「'/?'」と書いておくと、''でも'/'でもマッチングするのでした。同様に、'/test/'でも'/test'でもマッチングさせたいときには「'/test/?'」と書けばよいようです。
さて、このままではCGIでは動きません。:runがtrueになっているからです。これはMongrelやThinやWEBrickなどのアプリケーションサーバで動かす場合の設定です。アプリケーションサーバを使う場合はこのままで動きます。
CGIを使う場合のために、以下のようなdispatch.cgiを書きます。
#!/usr/bin/ruby require 'rubygems' load 'start.rb' set :run, false Rack::Handler::CGI.run Sinatra::Application
なんとなくrubygemsをrequireしていますが、本来はstart.rbで呼び出してくれるので不要なはず。
start.rbをrequireじゃなくてloadしているのは深い意味はありません。
そして:runをfalseに上書きしたあと、RackのCGIハンドラーを呼び出します。これでCGIとして動作するようになります。
ちなみに.htaccessはこんな感じです。
Options +ExecCGI AddHandler cgi-script cgi DirectoryIndex dispatch.cgi <Files start.rb> deny from all </Files> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*) dispatch.cgi/$1 [L]
start.rbは直接叩けないようdeny from allにしてあります。また、DirectoryIndexとRewriteRuleで、存在するファイル以外へのアクセスを全てdispatch.cgiで動かすようにしています。
こんな感じで書けば、Sinatraのソース自体はいじらずに、CGIでもアプリサーバでも動かせるようになるはずです。
ただ、本当はSinatraのソースをSinatra::Baseのサブクラスとして書く方が今っぽいのかもしれません。それなら同一プロセスで複数のSinatraアプリを共存させることもできるそうですし。まあでも、classレスですっきりしたソースがSinatraの魅力でもあるので、この辺りは好きずきでどうぞ。