malli

https://github.com/metosin/malli :malli:
ikitommi 2020-07-30T07:07:40.274400Z

as one string? Maybe something like:

(m/decode 
  [:vector {:decode/string (partial str/split ",")} int?] 
  "1,2,4,8,10"
  mt/string-transformer)
not near a computer, so not 100% sure it works

ikitommi 2020-07-30T07:08:37.275600Z

first splits the string, the decodes parts string->int

danielglauser 2020-07-30T16:07:19.277100Z

Thanks, I'll give that a try. I came up with this but your solution seems simpler:

(defn ids?                                                                      
  "Takes in a string and returns true if that string is of the form             
  1,4,7,9 or a sequence (in the math sense) of positive integers."              
  [data]                                                                        
  (let [ids (-> data                                                            
                (clojure.string/split #",")                                     
                (as-> ids (mapv #(Integer/parseInt %) ids)))]                   
    (every? pos? ids)))

(def GetClassesQueryOptions                                                     
  [:map                                                                        
   [:approved {:optional true} boolean?]                                        
   [:instructors {:optional true} [:fn (fn [ids] (ids? ids))]]                  
   [:machine {:optional true} [:fn (fn [ids] (ids? ids))]]                      
   [:music {:optional true} [:fn (fn [ids] (ids? ids))]]                        
   [:bookmarked {:optional true} boolean?]                                      
   [:minlength {:optional true} int?]                                           
   [:maxlength {:optional true} pos?]])

ikitommi 2020-07-30T17:20:12.284800Z

It's good to keep decoding and validation in separate steps. @alexmiller has many times called the spec conform "a meat grinder", as it bundles the two and runs the transformations every time.

2