2012年12月18日火曜日

Backbone、Collection.createのエラーハンドラ


Backboneのドキュメントを見るとCollection.createについて

コレクションに新しいモデルのインスタンスを作成するときの便利メソッド。プロパティのハッシュを用いてモデルのインスタンスを作成し、モデルをサーバに保存して、これに成功した後コレクションにモデルを追加するのと等価。返却値はモデル、但しバリデーションエラー時はfalseが返却されモデルは作成されない。…

と書いて有ります。
これのバリデーションエラーのハンドラの登録の仕方についてです。
結論から言うと、イベントに対するハンドラの登録ではなく、
createメソッドのオプションでerrorハンドラを登録すべしです。

以下だらだらとその理由について、

通常Backboneにおいて、いわゆるハンドラはイベントの形で登録するのが一般的かと思います、
// collectionの`reset`イベントのハンドラにrenderListメソッドを登録
this.collection.on('reset', this.renderList, this);
Collection.createでModel.validateが`undefined`以外を返却した場合
(バリデーションエラーの場合)も以下のように
`error`イベントを捕まえられるかと思いますが
this.collection.on('error', this.alertError, this);
実際にCollection.createメソッドでModel.validateは`undefined`以外を返却しているが、
`error`イベントは発火されない、
答えはこのissueにありました。

Collection.createが失敗した時コレクションにはまだそのモデルは追加されていないのだから、
コレクションがまだ持っていないモデルのエラーを通知するのはおかしいということです。

DocumentCloudの人にそう言われると納得します、
なんでもかんでもイベントではなくて、`error`オプションの方が適切な文脈も
在るということですね。

2012年9月30日日曜日

[{ key: 3 }, { key: 2 }, { key: 1 }].should be_sorted_by(:key, :desc)

[{ key: 3 }, { key: 2 }, { key: 1 }].should be_sorted_by(:key, :desc) 
って記述したくて書いてみました


…一般的な用途だし、ちゃんと探せばライブラリとかあるのかな?

2012年6月20日水曜日

mongoDB、MapReduceでカレンダー


コレクションを、指定された期間で日付をキーにMapReduceした帳票を出力する、
って割とありふれたニーズだと思います。例えばこんなコレクションがあって、

<TODO>
contentdoneinsert
hoge2012/06/192012/06/17
piyo2012/06/19
foo2012/06/212012/06/19

以下のようなある週の日毎のTodo消化数一覧を表示したいとか。

  {"_id"=>2012-06-16 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-17 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-18 15:00:00 UTC, "value"=>{"done_count"=>1.0}}
  {"_id"=>2012-06-19 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-20 15:00:00 UTC, "value"=>{"done_count"=>1.0}}
  {"_id"=>2012-06-21 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-22 15:00:00 UTC, "value"=>{"done_count"=>0}}

PostgreSQLならgenerate_seriesで日付のテーブルを作ってこれに結合すれば期待する結果が得られると思います、mongoでも同様のことがしたくて試行錯誤してみました、
rubyでの実装です、

至極単純で、map関数でemitされるのと同様の形式でカレンダーコレクションを前もって作っておいて、これにMapReduceの結果をmergeするだけです。
カレンダーコレクション―MapReduceの出力先はランダム文字列と共に生成、使用後はdropして、衝突しないようにしています。
* moment.jsインクルードしていますが、実はこのpullリクエスト通らないと動きません、
 

結局これって、一時的なコレクション作ってそれにjoinしてるわけで、カレンダーに限らずSQLのwith句駆使して実装してる処理とかも(泥臭く、且つ分かり易く)実装できそう。

2012年5月10日木曜日

git pullのhookをglobalに設定する


git pullした際にanythingのファイルリストを更新したかったのですが、
やり方分からなかったので調べました。

まずgit pullの際のhook、
post-mergeに記述すれば良いみたいです。

それからhookのglobalな設定、
git initした際のテンプレート用のディレクトリをglobalに設定すれば良いみたいです。

なので、
$ # git initの際のテンプレートディレクトリ
$ mkdir -p ~/.git_template/hooks
$ # pullした時に実行したい処理を記述
$ vi ~/.git_template/hooks/post-merge
$ chmod a+x ~/.git_template/hooks/post-merge
$ # ~/.git_templateをglobalに設定
$ git config --global init.templatedir '~/.git_template'
$ # 既存のgitにテンプレートを追加
$ cd <既存のgit>
$ git init

新規作成やクローンしたgitには最初から~/.git_template/hooksの中身が
適用されています。既存のgitにgit initして問題ないのか不安だったので調べてみたら、
既存のリポジトリにgit initを実行しても問題ないです。既存のファイルが上書きされるだけです。git initを実行する主な目的は新規に追加されたテンプレートを適用するためです。
関係ないですがanythingのファイルリストの更新については当然
rubikitchさんの記事を参考にしてます。