これからCouchDBのアプリケーション作るよ!って人向けに。

OSCで興味を持った人がいるかもしれないので、書いておきます。アプリケーションの構造そのものとかの基本的なことがらはz.ohnamiさんの記事参考にしてください

そろそろIDEなり使ってがりがりやりたいよ、となってきたら、CouchApp は必須です。
というかcouchapp.js などのJavaScriptライブラリはともかくとしてコマンドラインPythonツール(couchapp)は必須です。

$ sudo easy_install couchapp
$ couchapp generate app
$ cd app
$ couchapp push http://localhost:5984/db

で db に _design/app というデザインドキュメント放り込めます。app ディレクトリには shows とか lists とか views というディレクトリがあって、そこに js ファイルおいとけばいいです。

show/list/view

  • shows/s.js は _design/app/_show/s[/{id}] でアクセスできます
  • lists/l.js は _design/app/_list/l/{viewname} でアクセスできます
  • view/foo/map.js, view/foo/reduce.js は _design/app/_view/foo の map 関数とreduce関数です(reduce.jsはオプション)

.js 内で使えるマクロ

  • !code foo/bar/hoge とやると app/foo/bar/hoge.js のコードを埋め込みます(C の #include マクロと同じ)。
  • !json foo.bar.hoge とやると foo.bar.hoge.html の内容を foo.bar.hoge というJavaScriptの式で取得できるようにするJavaScriptが埋め込まれます。

マクロで埋め込むファイルは app 以下にあればどんなパスでもOKです。私はいつも app/templates app/lib というのを使うようにしています。

添付ファイル

_attachments は添付ファイル置き場なのでクライアント(ブラウザ)側で必要とするファイル(js/css/html)をおいとけばOKです。_attachments 以下にディレクトリを作ってその下にファイルを置く、でもOKです。例外的に vendor/foo/_attachments も添付ファイル置き場になりますが、こちらはディレクトリを掘るとうまく動きませんでした。

show, list の書き方

普通に return "クライアントに返すコンテンツ"; を定義すればOKです。関数の返り値がundefinedだと、500 エラーになるので慌てずに。

fucniton(doc, req){
   // 
}

これだとreturnがないので500です。

覚えておきたい関数

  • assetPath()

デザインドキュメントのWeb上のルートパスを返してくれます。例えば /db/_design/app とか。Proxy はさんで / を特定のDBにマッピングするとかそんなことをやられると意味がなくなるので注意。

  • template(String, Binding);

Stringの内容をテンプレートとして、文字列を生成します。Binding では {foo: "hoge"} などのオブジェクトを与えておきます。そうするとテンプレートの文字列内で<%= foo %> のような変数参照ができます。でもこのテンプレート関数 if とか for とか while とか 使えない(<%= (function(){})() %>ってやればいけるかも?) ので注意。

  • log(Object)

(/usr/local)/var/log/couch.log に OS Message : .... というログを出力します。出力する際はString,Number以外はJSONフォーマットの文字列になりますのでオブジェクト放り込んでかまいません。ただし、log([1, 2, undefined, 3]) のように undefined なものがあると落ちるので気をつけてください。

  • send(String)

list 関数内で、クライアントに文字列を即座に送信します。他の言語で output.write(string); flush(); とかやるようなもんです。大量のコンテンツがある場合 return でコンテンツを返す場合よりも効率的に返すことが出来ます。

  • provides(f, function(){});

?format={f} という形式で呼び出されたときや Accept: ... などのContent-Negotiationが行われるときを想定する場合に使います。

function(doc, req){
  provides("html", function(){ .... } );
  provides("json", function(){ .... } );
}

こんな感じで書いておくと htmlもjsonもどっちも応答できます。

  • sum(Array);

reduce.js で使う、とりあえず定義したかっただけだろ的な関数です。配列の各要素に+演算します。

FAQ(かどうかはしらないけどWebJourney作っていていろいろはまった点)

  • CouchAppのtemplate(String, Binding)が使い物にならねーぜ!

EJSを使うと幸せになれます。http://d.hatena.ne.jp/yssk22/20091006/1254835065

  • couchapp push し忘れるんだけど。

うちはMacでしか開発しないので RubyCocoaディレクトリモニタしてます(http://d.hatena.ne.jp/yssk22/20090814)。
emacs lisp とかでcouchappを飛ばすものでもいいと思います。

  • show/list/view いくつか作ったらFutonが重くなったよ!

そういうもんです:P。私も困ってます。しかし、irb と restclient でCLI操作できるのでFutonいらねんじゃね?とか思ったりすることもなくもないです。

  • Function Raised Error がでてもどこがエラーかわからないよ!

これはcouchjs(spidermonkey)が悪いのでランタイムハックしましょう。私はまだ log() でなんとかがんばってますがそろそろ限界。

  • instanceof とか typeof とかがおかしくないかい?

私もそう思います。。。前dev MLにも投げたんですがランタイムハックしないとだめそうで、その時間がとれてません。JavaScriptをサーバーサイドで安全に動かすための sandboxモデル がなにやら悪さをしてそうです。とりあえず instanceof Array が使えないと結構死ねるのですが、

if( (typeof object) == "object" && object.length && object.length >= 0){ 
  // これはArray 
}else{
  // Arrayじゃない
}

として、length を普通のObjectに使わない、と誓いを立てて作業しています。

以上、ひとまず。