diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/reverse_routing/core.clj | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/src/reverse_routing/core.clj b/src/reverse_routing/core.clj index 4299eba..1977b2a 100644 --- a/src/reverse_routing/core.clj +++ b/src/reverse_routing/core.clj @@ -6,17 +6,17 @@ (def ^:private ^:dynamic *lookup-route* nil) (def ^:private ^:dynamic *root* nil) +(defn ^:private deref-if-var [arg] + (if (var? arg) + (deref arg) + arg)) + (defn wrap-reverse-routing [handler & {:keys [root] :or {:root ""}}] (fn [request] (binding [*lookup-route* (->> handler deref-if-var meta ::lookup) *root* root] (handler request)))) -(defn ^:private deref-if-var [arg] - (if (var? arg) - (deref arg) - arg)) - (defn ^:private lookup-route [route & handlers] (->> handlers (map (comp ::lookup meta deref-if-var)) @@ -33,7 +33,7 @@ `(let ~bindings (routes ~@handlers))) (defmacro when-routes [cond & handlers] - `(when ~cond (routes ~@handlers))) + `(if ~cond (routes ~@handlers) (routes))) (defmacro defroutes [name & handlers] `(def ~name (routes ~@handlers))) @@ -42,15 +42,16 @@ (let [string-path (if (vector? path) (first path) path) path-keys (vec (:keys (clout.core/route-compile string-path))) keylen (count path-keys) - lookup-fn `(fn [[route-name# args-count#]] - (let [~args (repeat nil) ;; hacky, but necessary - provide nil values for args - r# (#'lookup-route [route-name# (- args-count# ~keylen)] - ~@routes) - {uri# :uri, args# :args} r#] - (if r# - (assoc r# - :uri (str ~string-path uri#) - :args (vec (concat ~path-keys args#))))))] + lookup-fn `(fn [[route-name# args#]] + (if (>= (count args#) ~keylen) + (let [~args args# + r# (#'lookup-route [route-name# (vec (drop ~keylen args#))] + ~@routes) + {uri# :uri, args# :args} r#] + (if r# + (assoc r# + :uri (str ~string-path uri#) + :args (vec (concat ~path-keys args#)))))))] `(vary-meta (compojure.core/context ~path ~args (routes ~@routes)) assoc ::lookup ~lookup-fn))) @@ -58,20 +59,21 @@ (defmacro register-route [route-name [type path args & body :as route]] (let [string-path (if (vector? path) (first path) path) route-args (:keys (clout.core/route-compile string-path)) - route-id [route-name (count route-args)] routes-map {:uri string-path :type (keyword (string/lower-case (name type))) :args (vec route-args)}] `(vary-meta ~route - assoc ::lookup (fn [signature#] - (if (= signature# ~route-id) + assoc ::lookup (fn [[name# args#]] + (if (and (= name# ~route-name) + (= (count args#) (count ~(vec route-args)))) ~routes-map))))) (defn url-for [route & arg-values] - (let [{:keys [uri type args]} (*lookup-route* [route (count arg-values)]) + (let [spec (*lookup-route* [route arg-values]) + {:keys [uri type args]} spec root-path *root*] - (assert uri) - (str root-path - (reduce (fn [string [name val]] - (clojure.string/replace string (str name) (str val))) - uri (map vector args arg-values))))) + (if spec + (str root-path + (reduce (fn [string [name val]] + (clojure.string/replace string (str name) (str val))) + uri (map vector args arg-values)))))) |