Skip to content

Instantly share code, notes, and snippets.

@pandeiro
Created January 10, 2012 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pandeiro/1590298 to your computer and use it in GitHub Desktop.
Save pandeiro/1590298 to your computer and use it in GitHub Desktop.
CouchDB type in Clojure
(ns noir-couchdb.core
(:use [com.ashafa.clutch :only [get-database put-document delete-document
get-document database-info all-documents
get-view]])
(:require [com.ashafa.clutch.utils :as clutch]
[clojure.string :as string])
(:refer-clojure :exclude (conj! assoc! dissoc!)))
(defprotocol CouchOps
"Defines side-effecting operations on a CouchDB database.
All operations return the CouchDB database reference —
with the return value from the underlying clutch function
added to its :result metadata — for easy threading and
reduction usage."
(create! [this]
"Ensures that the database exists, and returns the database's meta info.")
(conj! [this document]
"PUTs a document into CouchDB. Accepts either a document map (using an :_id value
if present as the document id), or a vector/map entry consisting of a
[id document-map] pair.")
(assoc! [this id document]
"PUTs a document into CouchDB. Equivalent to (conj! couch [id document]).")
(dissoc! [this id-or-doc]
"DELETEs a document from CouchDB. Uses a given document map's :_id and :_rev
if provided; alternatively, if passed a string, will blindly attempt to
delete the current revision of the corresponding document."))
(defprotocol CouchView
"Defines method(s) for retrieving a CouchDB view"
(view [this view-key]
"GETs a pre-defined CouchDB view")
(add-view [this view-key design view opts]
"Registers a view and its options to key"))
(defn- with-result-meta [couch result]
(vary-meta couch assoc :result result))
(defn- add-view-to-meta [couch view]
(assoc-in (meta couch) [:views] view))
(deftype CouchDB [url meta]
CouchView
(view [this view-key]
(meta this))
(add-view [this view-key design view opts]
(add-view-to-meta this {view-key (fn [] (get-view url design view opts))}))
CouchOps
(create! [this] (with-result-meta this (get-database url)))
(conj! [this doc]
(let [[id doc] (cond
(map? doc) [(:_id doc) doc]
(or (vector? doc) (instance? java.util.Map$Entry)) doc)]
(with-result-meta this (put-document url doc :id id))))
(assoc! [this id document] (conj! this [id document]))
(dissoc! [this id]
(if-let [d (if (#'com.ashafa.clutch/document? id)
id
(get this id))]
(with-result-meta this (delete-document url d))
(with-result-meta this nil)))
clojure.lang.ILookup
(valAt [this k] (get-document url k))
(valAt [this k default] (or (.valAt this k) default))
clojure.lang.Counted
(count [this] (:doc_count (database-info url)))
clojure.lang.Seqable
(seq [this]
(->> (all-documents url {:include_docs true})
(map :doc)
(map #(clojure.lang.MapEntry. (:_id %) %))))
clojure.lang.IMeta
(meta [this] meta)
clojure.lang.IObj
(withMeta [this meta] (CouchDB. url meta)))
(defn couch
([url]
(CouchDB. (assoc (clutch/url url)
:username "moi" :password "password") nil))
([url meta]
(CouchDB. (assoc (clutch/url url)
:username "moi" :password "password") meta)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment