Skip to content

Instantly share code, notes, and snippets.

@jcromartie
Created July 28, 2011 14:59
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 jcromartie/1111698 to your computer and use it in GitHub Desktop.
Save jcromartie/1111698 to your computer and use it in GitHub Desktop.
(ns cklist.model.generic
(use cklist.util))
;; =========================================================================
;; revision and timestamping support
(defn timestamp
"Returns object timestamped with the current system time in milliseconds"
[obj]
(assoc obj :timestamp (System/currentTimeMillis)))
(defn current
"Returns current state of object without any history"
[obj]
(dissoc obj :revisions))
(defn revision
[obj f & args]
(let [rev (:rev obj 0)]
(-> (apply f obj args)
(update-in [:revisions] assoc rev (assoc (current obj) :rev rev))
(assoc :rev (inc rev))
(timestamp))))
(defmacro rev->
"Returns revisioned update of obj by threading it through
forms (like with ->)"
[obj & forms]
`(revision ~obj #(-> % ~@forms)))
(defn history
"Returns all states of model object, oldest first"
[obj]
(sort-by :rev
(conj (vals (:revisions obj))
(dissoc obj :revisions))))
;; =========================================================================
;; simple hash-map based repository
(defn new-model-object
"Returns new, uniquely identified, timestamped object with initial
key-val pairs"
[& key-vals]
(timestamp (merge (apply hash-map key-vals)
{:uuid (uuid)
:revisions (sorted-map)})))
(defn store
"Store domain object in repo"
[repo obj]
{:pre [(map? repo) (:uuid obj)]}
(assoc repo (:uuid obj) obj))
(defn find-all
"Return all domain objects in repo"
[repo]
{:pre [(map? repo)]}
(vals repo))
(defn find-by-id
[repo id]
{:pre [(map? repo) id]}
(get repo id))
(defn find-by
"Find values matching pred"
[pred repo]
(filter pred (find-all repo)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment