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
あんまりCouchDBもRubyよく知らないのでツッコミ歓迎
#追記
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を見ていないようなので大丈夫かなと、、