Cloudant+ActiveResource
nosqlgogoに行ってきた!
そこでCouchDBについて初めて聴き、RESTful APIを持っているならActiveResourceで接続できるんじゃないか?と思い、Cloudantの2GB無料アカウントをもらったのでブログでも作ってみようと試してみた。
で、現在挫折中。残骸はgithubにあげてある。 実際はCouchRest Modelが使えそう(教えてくれた@d6rkaizさんありがとう!)。
一応作業のメモ。これでfind, firstは使えるようになる。
- CloudantというActiveResource::Baseを継承した抽象クラスを作り、そこでCloudantにあるCouchDBとのやりとりを仲介することにした
- レスポンスはすべてJSONで返ってくるが、APIのURL末尾に.jsonが不要なのでcollection_path、element_path、new_element_pathから.jsonを除く
- さらにCouchDBでドキュメントの一覧を取得するには/some_documents/_all_docsというURLになるのでcollection_pathに_all_docsを書き加える
- またドキュメントの一覧を取得した場合には以下のように多段rowsというキーに対して配列
- 各ドキュメントごとに_idというプライマリキーを持つのでself.primary_keyを書き換える。ただしActiveResource::Baseのクラス変数のprimary_keyは継承したクラスごとに設定されてしまうため、そのままでは子クラスで共通して使うことができない。そこでcattr_accessorで上書きしてから使う。
class Cloudant < ActiveResource::Base self.site = "https://#{CLOUDANT_USER}.cloudant.com/" self.user = CLOUDANT_USER self.password = CLOUDANT_PASS self.format = :json # primary_key is for each model by default, # so override them by one class variable cattr_accessor :primary_key self.primary_key = "_id" def id_from_response(response) return nil if response.body.empty? ::JSON.parse(response.body)["id"].to_i end class << self def collection_path(prefix_options = {}, query_options = nil) prefix_options, query_options = split_options(prefix_options) if query_options.nil? "#{prefix(prefix_options)}#{collection_name}/_all_docs#{query_string(query_options)}" end def element_path(id, prefix_options = {}, query_options = nil) prefix_options, query_options = split_options(prefix_options) if query_options.nil? "#{prefix(prefix_options)}#{collection_name}/#{URI.escape id.to_s}#{query_string(query_options)}" end def new_element_path(prefix_options = {}) "#{prefix(prefix_options)}#{collection_name}/new" end # in cloudant response collections are wrapped in a hash, so we have to peal them def instantiate_collection_with_cloudant(collection, prefix_options = {}) if collection.is_a?(Hash) && collection["rows"].present? rows = collection["rows"].map { |row| { "_id" => row["id"] } } instantiate_collection_without_cloudant(rows, prefix_options) else instantiate_collection_without_cloudant(collection, prefix_options) end end alias_method_chain :instantiate_collection, :cloudant end end