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さんの記事を参考にしてます。


2011年10月30日日曜日

FacebookのQuestionを取得

Geaph APIでQuestionが取得できるようになったそうです。 https://developers.facebook.com/docs/reference/api/question/ 
自分があまりQuestionを利用しないのでこのAPIの需要が分かっていないんですが…

  • Questionsの取得には「user_questions」又は「friends_questions」のpermissionが必要
  • /USER_ID/questionsでUSER_IDのQuestion一覧を取得
  • /QUESTION_ID/optionsで選擇肢を取得(この情報は/USER_ID/questionsに含まれているけど。。。) 
  • /QUESTION_OPTION_ID/votesで投票したユーザの一覧を取得 


試してみました、
require 'haml'
require 'koala'
require 'omniauth'
require 'rubygems'
require 'sinatra'

APP_ID = "212005055538084"
APP_SECRET = "hogehoge"

enable :sessions

use OmniAuth::Strategies::Facebook, APP_ID, APP_SECRET, :scope => 'user_questions' 

get '/auth/facebook/callback' do
  auth_hash = request.env["omniauth.auth"]
  uid = auth_hash["uid"]
  token = auth_hash["credentials"]["token"]
  graph = Koala::Facebook::API.new token

  result = graph.batch do |api|
    # 毎回:batch_args => ...て書くの気持ち悪いので特異メソッド定義
    def api.get_connects(id, conn, name="")
      self.get_connections(
        id, conn, {}, 
        :batch_args => { :name => name, :omit_response_on_success => false})
    end

    api.get_connects uid, "questions", "get-qs"
    api.get_connects "{result=get-qs:$.data[0].id}", "options", "get-ops"
    api.get_connects "{result=get-ops:$.data[0].id}", "votes"
    api.get_connects "{result=get-ops:$.data[1].id}", "votes"
    api.get_connects "{result=get-ops:$.data[2].id}", "votes"
  end

  haml '%div= result.to_s', :locals => { :result => result }

end
こんなjson返ってきました。
[
  [
    {
      "id": "170514669705292",
      "from": {
        "name": "Sinjin Ra",
        "id": "100002402797320"
      },
      "question": "今年の流行語は?",
      "created_time": "2011-10-30T12:25:51+0000",
      "updated_time": "2011-10-30T12:25:51+0000",
      "options": {
        "data": [
          {
            "id": "267486769961495",
            "from": {
              "name": "Sinjin Ra",
              "id": "100002402797320"
            },
            "name": "トゥットゥルー",
            "votes": 3,
            "created_time": "2011-10-30T12:25:50+0000"
          },
          {
            "id": "234349516624548",
            "from": {
              "name": "Sinjin Ra",
              "id": "100002402797320"
            },
            "name": "ドラマチックこそ、 人生です。",
            "votes": 2,
            "created_time": "2011-10-30T12:25:48+0000"
          },
          {
            "id": "309092772438842",
            "from": {
              "name": "Sinjin Ra",
              "id": "100002402797320"
            },
            "name": "ほびろん",
            "votes": 2,
            "created_time": "2011-10-30T12:25:49+0000"
          }
        ],
        "paging": { ...
..]

Herokuで試してみました、初Herokuです、
デプロイ(git push)したらアプリが動いているって画期的です、
…久々にClojure触りたくなってきました(HerokuはClojureもサポート)

2011年10月23日日曜日

OS XにGaucheをインストール


Shibuya.lispテクニカルトーク第7回行ってきました、
Shibuya.lisp、初参加です、

なにはともあれインパクト強すぎました、
Lispマシンを作ってみた(Youtube動画)
結局Lisp系って、「ないから」ではなく「あるけど」
「作りたいから作った」人が多いですね、

なので、久しぶりにScheme処理系作りたいと思いました。
事始めにGaucheのソースを追う環境を構築したのでその備忘録:

■Gaucheのインストール
・SLIB
$ cd ~/Downloads
$ curl -O http://groups.csail.mit.edu/mac/ftpdir/scm/slib-3b3.zip
$ unzip slib-3b3.zip 
$ cp -r slib ~/opt/slib
・Gauche
ダウンロード後、
$ tar zxvf Gauche-0.9.2.tgz
$ cd Gauche-0.9.2/
$ ./configure --prefix=/Users/tajima_junpei/opt/Gauche-0.9.2 --with-slib=/Users/tajima_junpei/opt/slib
$ make
$ make install
$ echo "export PATH=\$PATH:/Users/tajima_junpei/opt/Gauche-0.9.2/bin" >> ~/.bashrc
$ source ~/.bashrc
・確認
$ gosh
gosh> (define (fact n) (if (> n 1) (* n (fact (- n 1))) 1))
fact
gosh> (fact 10)
3628800
gosh> (use slib)
#
gosh> (require 'trace)
#t
gosh> (trace fact)
#
gosh> (fact 5)
CALL fact 5
  CALL fact 4
    CALL fact 3
      CALL fact 2
        CALL fact 1
        RETN fact 1
      RETN fact 2
    RETN fact 6
  RETN fact 24
RETN fact 120
120
gosh> 

■ソースを追うための準備
・GLOBALのインストール
$ cd ~/Downloads
$ curl -O http://tamacom.com/global/global-6.1.tar.gz
$ tar zxvf global-6.1.tar.gz
$ cd global-6.1/
$ ./configure --prefix=/Users/tajima_junpei/opt/global-6.1
$ make
$ make install
~/.emacs.d/.init.elに追記
;; gtags
(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
      '(lambda ()
         (local-set-key "\M-t" 'gtags-find-tag)
         (local-set-key "\M-r" 'gtags-find-rtag)
         (local-set-key "\M-s" 'gtags-find-symbol)
         (local-set-key "\C-t" 'gtags-pop-stack)
         ))

(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
      '(lambda ()
         (local-set-key "\M-t" 'gtags-find-tag)
         (local-set-key "\M-r" 'gtags-find-rtag)
         (local-set-key "\M-s" 'gtags-find-symbol)
         (local-set-key "\C-t" 'gtags-pop-stack)
         ))
ソースの関数上でM-tでタグジャンプ

■ソースの追い方
Emacs上にて
M-x gdb
gdb --annotate=3 gosh
(gdb) break repl_read_cc
Breakpoint 1 at 0x20c49ba5d77dd1: file repl.c, line 103.
(gdb) r
Starting program: /Users/tajima_junpei/opt/Gauche-0.9.2/bin/gosh 
Reading symbols for shared libraries ++. done
gosh> (+ 1 1)

関数repl_read_cc上にて実行が止まる、
「s」でステップ実行、「p」で変数のインスペクト

2011年9月9日金曜日

Google APIクライアントライブラリ

今日まで気付かなかったのですが、
最近のGoogle Codeのブログ、やたらとGoogle APIクライアントライブラリに関する投稿が多いです。

これらプロジェクトの関連を見つけられていないんですが、
何かしら大元のプロジェクトの存在が窺えるような…

Googleのライブラリって
「YouTubeであればPythonとPHPと…のライブラリが提供さえている」と、
プロダクトごとにカテゴライズされるイメージが強いですが、
最近のGoogle Codeブログの投稿を見ていると、
「各言語について、すべてのGoogleプロダクトのAPIを提供する(つもりの)ライブラリを準備中…」
と読めなくもないような

探してみたらRubyのライブラリもありました、お陰で週末の予定も埋まりました。


…Google三大言語なんて既に、Googler以外の人が信じる迷信なんじゃないだろうか?

* 2011/9/15 追記
ターゲットはGoogle+ APIだったんですね、なるほどー