API question about the solutions to this issue. I started implementing the third option below and found it a bit awkward. The json encoding function takes a map of key/value pairs and a boolean (whether or not to json encode the entire map) and returns a string. To make this easier, I made map-to-query-str accept a predicate, executed on each key to determine whether or not the value should be encoded. It then seemed pretty natural to add that to get-document
(get-document "doc-id" {:option1 "some val" :rev "..."} #{:rev}) ;; <-- using the set indicate which keys should not be encoded
(get-document "doc-id" {:option1 "some val"}) ;;<-- works the same as before
The existing two arg get document still works the same way, it just delegates using (constantly false)
(defn get-document
"Takes an id and an optional query parameters map as arguments and returns a
document (as a map) with an id that matches the id argument."
([id]
(get-document id {}))
([id query-params-map]
(get-document id query-params-map (constantly false)))
([id query-params-map keys-not-encoded-fn?]
(if (and id (not (empty? id)))
(couchdb-request config :get
:command (str (utils/uri-encode id)
(utils/map-to-query-str query-params-map
(comp not keys-not-encoded-fn?)))))))
map-to-query-str just changes from the boolean to the function:
(defn map-to-query-str
([m]
(map-to-query-str m (constantly true)))
([m params-not-encoded-fn?]
(when-let [kws (keys m)]
(reduce
(fn [q kw]
(let [k (if (keyword? kw) (name kw) kw)
v (if (params-not-encoded-fn? kw) ;;<--- Switched to use function
(json/json-str (m kw))
(str (m kw)))
a (if (not (= (last kws) kw)) "&")]
(str q (uri-encode k) "=" (uri-encode v) a)))
"?" kws))))
Is this more straight-forward? A bonus is that the caller doesn't need to know that they pass in "_rev" as a key (not something that CouchDB would accept) that Clutch will spot it and rename it to "rev".
-Ryan