Last active
February 20, 2016 17:42
-
-
Save quephird/4d3dac813b61ce477778 to your computer and use it in GitHub Desktop.
Inspired by some code I read this past week.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; After seeing some code whereby a suite of function implementations for CRUD operations | |
;; for a set of object types were exactly the same except for the entity in question, | |
;; I wondered if there was a way to somehow share implementations. It's not quite OO | |
;; inheritance but this seems to do the job; I have no idea if this is considered | |
;; idiomatic Clojure code. | |
(ns fun-with-protocols-and-records) | |
;; Based on http://david-mcneil.com/post/1475458103/implementation-inheritance-in-clojure | |
;; | |
;; This example illustrates how to pass things other than the record type itself | |
;; to the protocol functions. | |
;; Create a base record type representing an object | |
;; that can map to a datanase table, identified | |
;; by the table and db parameters. | |
(defrecord Entity [table db]) | |
;; This defines a protocol that establishes | |
;; the set of CRUD operations that must be implemented. | |
(defprotocol Persistable | |
(find [entity id]) | |
(update [entity id attrs]) | |
(insert [entity attrs])) | |
;; This defines a baseline set of implementations. | |
(def crud-ops | |
{:find (fn [entity id] | |
(str "Found a " (:table entity) " with id " id " in " (:db entity) ".")) | |
:update (fn [entity id attrs] | |
(str "Updated attributes " attrs " of a " (:table entity) " with id " id " in " (:db entity) ".")) | |
:insert (fn [entity attrs] | |
(str "Inserted a new " (:table entity) " with attributes " attrs " in " (:db entity) "."))}) | |
;; This provides the implementations above to the protocol, | |
;; and associates them with the Entity record type. | |
(extend Entity | |
Persistable | |
crud-ops) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Create some entities | |
(def person (Entity. :person :oracle-instance)) | |
(def address (Entity. :address :postgress-instance)) | |
;; Do some CRUD ops and see that they "touch" different | |
;; tables and databases even though it's the same API calls | |
;; for each record type. | |
(find person 42) | |
(insert address {:street "123 Main Street" :city "New York" :state-code "NY"}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment