clojure - How to remove duplication in request validation? -


i have compojure app set of routes , handlers.

(defroutes app-routes   (get "/stuff/:id" [:as request] (stuff/get-stuff request))   (post "/stuff/" [:as request] (stuff/create-stuff request)) 

each handler validates input, so

(defn create-stuff   [request]   (my-validation/validate-request     request     my-validation/create-stuff-validator     stuff-ok-fn)) 

the validation code based on metis, , looks this:

(metis/defvalidator :create-stuff-validator   [:db :presence])  (defn validate-request   [request request-validator ok-function]   (let [validation-result (request-validator request)]     (if (empty? validation-result)       (ok-function request)       (bad-request validation-result)))) 

my problem code in create-stuff duplicated across each of route handlers; i.e get-stuff function looks create-stuff handler. thing differs validator function , the-validation-went-well-function.

how can abstract duplication in idiomatic clojure manner?

since functional language, suggest passing functions differentiate handlers generic handler function.

;;; in core.clj (defroutes app-routes   (get "/stuff/:id" [:as request]        (handlers/handle         my-validation/get-stuff-validator         stuff/get-stuff-ok-fn         request))   (post "/stuff/" [:as request]         (handlers/handle          my-validation/create-stuff-validator          stuff/create-stuff-ok-fn          request)))  ;;; in handlers.clj  (defn handle   [validator action request]   (let [validation-result (validator request)]     (if (empty? validation-result)       (action request)       (bad-request validation-result)))) 

stylistically, suggest code easier read if avoid the smurf naming convention. namespace tells if validating, or "stuff" operating on, don't need include in name of function. also, fact passing argument should callable sufficient, don't need put fn in name of function, fact passed ok branch tells thing when things go ok.

;;; in core.clj (defroutes app-routes   (get "/stuff/:id" [:as request]        (handlers/handle         my-validation/get-stuff         stuff/get         request))   (post "/stuff/" [:as request]         (handlers/handle          my-validation/create-stuff          stuff/create          request)))  ;;; in handlers.clj  (defn handle   [validator ok request]   (let [errors (validator request)]     (if (empty? errors)       (ok request)       (bad-request errors)))) 

if can reduce verbosity without losing clarity, improve correctness, because errors hide in verbosity.


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -