Querying for Specific Revisions

21 views
Skip to first unread message

Ryan Senior

unread,
Jan 8, 2011, 6:15:14 PM1/8/11
to clojure...@googlegroups.com
When using get-document in Clutch, it allows for a query parameters map:

 (with-db "db1"
        (get-document "386d0400e336e54933a47aec656289c4" {:rev "7-ac7e4d143dff32f7be437de99a659ba1"})) ;; 500 error

And it automatically converts the query parameters map to JSON values, which includes putting quotes in the string like

(com.ashafa.clutch.utils/map-to-query-str {:rev "7-ac7e4d143dff32f7be437de99a659ba1"})
=>"?rev=%227-ac7e4d143dff32f7be437de99a659ba1%22"

However that doesn't work for CouchDB ({"error":"unknown_error","reason":"badarg"}). 

The value of rev needs to not be jsonified, like:

(com.ashafa.clutch.utils/map-to-query-str {:rev "7-ac7e4d143dff32f7be437de99a659ba1"} false)
=> "?rev=7-ac7e4d143dff32f7be437de99a659ba1"

http://localhost:5984/db1/386d0400e336e54933a47aec656289c4?rev=7-ac7e4d143dff32f7be437de99a659ba1 ;; works

Is there another way to go about this?  Should get-document be changed to allow passing in an arg to map-to-query-str?

-Ryan

Tunde Ashafa

unread,
Jan 11, 2011, 11:43:26 AM1/11/11
to clojure...@googlegroups.com
Hi Ryan, Let me look into this a bit. I'll get back to you asap.

Tunde Ashafa

unread,
Jan 19, 2011, 8:54:03 AM1/19/11
to clojure...@googlegroups.com
Hello Ryan,

Sorry for the late response, there are several ways I think we could go about this. A few that come to mind is:

  • to create specific APIs for getting specific document revisions (this was on my TODO list) 
  • we could also supply a second map in the "get-document" method that Clutch doesn't not urlencode the values of this map
  • keys starting with an underscore in the map provided to "get-document" don't have their values urlencoded and clucth would remove the underscore before the http request to CouchDB
I am leaning towards the last but they all have their pros and cons. Let me know what you think.

-Tunde. 
  



Ryan Senior

unread,
Jan 21, 2011, 8:00:21 PM1/21/11
to clojure...@googlegroups.com
I think all are good approaches.  Would you like me to tackle the last one?

-Ryan

Tunde Ashafa

unread,
Jan 22, 2011, 7:16:28 PM1/22/11
to clojure...@googlegroups.com
Hey Ryan, 

That would be awesome! :)

Thanks, Tunde. 

Ryan Senior

unread,
Jan 27, 2011, 12:14:26 AM1/27/11
to clojure...@googlegroups.com
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

Tunde Ashafa

unread,
Jan 28, 2011, 9:05:30 AM1/28/11
to clojure...@googlegroups.com
Hey Ryan, I like it. Send me a pull request including any tests you have and I'll merge and prep a v0.2.4.

Thanks!

-Tunde.     

Ryan Senior

unread,
Jan 29, 2011, 5:23:35 PM1/29/11
to clojure...@googlegroups.com
Sent, added a test for the JSON encoding in clutch/utils.clj as well.  I get 500 errors when I run the clutchapp tests, not sure why, but I haven't made any changes to that.

Do you know when the 0.2.4 release is going to be cut?

-Ryan
Reply all
Reply to author
Forward
0 new messages