diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 29bb6fc9..ac3e50b1 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -16,6 +16,7 @@ * [Data-specs](coercion/data_spec_coercion.md) * [Advanced](advanced/README.md) * [Configuring Routers](advanced/configuring_routers.md) + * [Composing Routers](advanced/composing_routers.md) * [Different Routers](advanced/different_routers.md) * [Route Validation](advanced/route_validation.md) * [Dev Workflow](advanced/dev_workflow.md) diff --git a/doc/advanced/README.md b/doc/advanced/README.md index cad41444..6069fb9f 100644 --- a/doc/advanced/README.md +++ b/doc/advanced/README.md @@ -1,5 +1,6 @@ # Advanced * [Configuring Routers](configuring_routers.md) +* [Composing Routers](composing_routers.md) * [Different Routers](different_routers.md) * [Route Validation](route_validation.md) diff --git a/doc/advanced/composing_routers.md b/doc/advanced/composing_routers.md new file mode 100644 index 00000000..b56d58b4 --- /dev/null +++ b/doc/advanced/composing_routers.md @@ -0,0 +1,79 @@ +# Composing Routers + +Routers expose both their routes and options via the `Router` protocol, enabling one to create new routers from existing ones. + +## Adding routes to an existing routers + +Let's define a router in an `Atom`: + +```clj +(require '[reitit.core :as r]) + +(def router (atom (r/router + [["/foo/bar" identity] + ["/foo/bar/:id" identity]]))) + +(r/routes @router) +;[["/foo/bar" {:handler #object[clojure.core$identity]}] +; ["/foo/bar/:id" {:handler #object[clojure.core$identity]}]] +``` + +A helper to add new route to a router: + +```clj +(defn add-route [router route] + (r/router + (conj (r/routes router) route) + (r/options router))) +``` + +Now, we can add routers to the router: + +```clj +(swap! router add-route ["/foo/bar/:id/:subid" identity]) + +(r/routes @router) +;[["/foo/bar" {:handler #object[clojure.core$identity]}] +; ["/foo/bar/:id" {:handler #object[clojure.core$identity]}] +; ["/foo/bar/:id/:subid" {:handler #object[clojure.core$identity]}]] +``` + +Router is recreated, so all the rules are fires: + +```clj +(swap! router add-route ["/foo/:fail" identity]) +;CompilerException clojure.lang.ExceptionInfo: Router contains conflicting routes: +; +; /foo/bar +;-> /foo/:fail +``` + +## Merging routers + +Given we have two routers: + +```clj +(def r1 (r/router ["/route1" identity])) +(def r2 (r/router ["/route2" identity])) +``` + +We can create a new router, with merged routes and options: + +```clj +(def r12 (r/router + (merge + (r/routes r1) + (r/routes r2)) + (merge + (r/options r1) + (r/options r2)))) + +(r/routes r12) +;[["/route1" {:handler #object[clojure.core$identity]}] +; ["/route2" {:handler #object[clojure.core$identity]}]] +``` + +## TODO + +* `reitit.core/merge-routes` to effectively merge routes with route data +