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