CouchRest::ExtendedDocumentを使ってみる。

Couchrestを使ってRubyからCouchdbにアクセスしてみます。

今回はCouchRest::ExtendedDocumentを使うとRailsからActiveRecordのように扱えるみたいなのでそれを試してみます。

couchdb自体はcloudant.comのクラウドを使っています。(ソースのURLはローカルにしていますが)250MBまでなら無料で使えるのでテスト目的のこれで良いでしょう。

ひとまずインストール

jruby -S gem install couchrest
jruby -S gem install couchrest_extended_document

もともとcouchrestにCouchRest::ExtendedDocumentが含まれていたらしいですが、抜き出された?っぽいです。

次にコード下記のようなのを書いてtest.rbとして保存しておきます。

# CouchdbのURLは適宜変更
DB = CouchRest.database!("http://localhost:5984/dbname")
class Test < CouchRest::ExtendedDocument
        use_database DB
        timestamps!
end

database!だとDBがないときに勝手につくります。すでにある場合はdatabaseで良いです。

あとはActiveRecordの如く使えるみたいです。

試しにドキュメントを追加してみます。

@data = Test.new("key" => "test", "value" => "value")
@data.save
p @data

すると下記のようにストアされてました。

{
   "couchrest-type"=>"Test", 
   "_id"=>"e5fa6bfe7849a200b9af23111ec8d483",
   "_rev"=>"1-dd8884aef4ad1d36e8f38121fa5441cd",
   "key"=>"test",
   "value"=>"value", 
   "updated_at"=>Sat Aug 28 21:48:11 +0900 2010, 
   "created_at"=>Sat Aug 28 21:48:11 +0900 2010, 
}

couchrest-type,updated_at,created_atというのが勝手に追加されているようです。

今度は全件取り出してみます。

@list = Test.all
p @data

これで全件取り出せました。

後ろでは下記のような感じでリクエストされていました。

http://localhost/dbname/_design/Test/_view/all?include_docs=true

Futonから寝転がって見てみると。。

下記のようなDesignDocumentが追加されていました。

{
   "_id": "_design/Test",
   "_rev": "1-78e521abd8a961432f957a98e5ef4751",
   "language": "javascript",
   "views": {
       "all": {
           "map": "function(doc) {\n                  if (doc['couchrest-type'] == 'Test') {\n                    emit(doc['_id'],1);\n                  }\n                }"
       }
   }

全件取るためのMapReduceも勝手に登録されています。
CouchAppより便利かも。


キー指定で1件取るにはこんな感じ

@data = Test.find('e5fa6bfe7849a200b9af23111ec8d483')
p @data

ただ、couchrest-typeというキー勝手につくって見ているのが嫌だなぁ、、これのおかげで既存のドキュメントが検索出来なくてはまりました。。。

なんかjsonをORMでラップすること自体負けてる気がしますが、、これでRailsから便利に使えそうなのでよしとします。。

その他詳細な使いかは下記を参考に
http://github.com/couchrest/couchrest_extended_document

あんまりCouchDBRubyよく知らないのでツッコミ歓迎


#追記

couchrest-typeが邪魔なので、何とかしようとGrepかけてみると、見事なハードコード&直したくなるなる件数w ドキュメントの種類を持っておきたいのは反対しないけど、この名前は嫌だ。。Ruby以外からも使うし。。

なのでとりあえずこういう逃げで、、

class Test < CouchRest::ExtendedDocument
        use_database DB
        timestamps!

        set_callback :save, :before, :set_type

        def set_type
                self['type'] = self['couchrest-type']
        end

        view_by :all,
                :map => "function() {
                        if (doc.type == 'Test' || doc['couchrest-type'] == 'Test') {
                                emit(doc['_id'], 1);
                        }
                }"

end

couchrest-typeの値をtypeにも保存、viewを作成してtypeも観るように、、findはcouchrest-typeを見ていないようなので大丈夫かなと、、