Skip to content

Instantly share code, notes, and snippets.

@pleasetrythisathome
Created October 7, 2014 19:05
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pleasetrythisathome/7adbdc9c8b7ab689df45 to your computer and use it in GitHub Desktop.
Save pleasetrythisathome/7adbdc9c8b7ab689df45 to your computer and use it in GitHub Desktop.
some code stripped out of a project showing use of silk for isomorphic routing
(ns router
#+cljs (:require-macros [cljs.core.match.macros :refer [match]])
(:require [domkm.silk :as silk]
[clojure.string :as str]
#+clj [content :as content]
#+clj [drivers.email :as email]
#+clj [clojure.core.match :refer [match]]
#+clj [compojure.core :as compojure :refer [defroutes GET POST PUT DELETE]]
#+clj [compojure.route :as route]
#+clj [com.stuartsierra.component :as component]
#+clj [render :as render]
#+clj [ring.util.response :as response]
#+cljs [cljs.core.match]
#+cljs [utils.helpers :as h]))
(def app-routes
(silk/routes [[:home [[]]]
[:section [[:page]]]
[:news [["news" :post]]]]))
(defmulti route->section :domkm.silk/name)
(defmethod route->section :default
[_]
[:home])
(defmethod route->section :section
[{:keys [page]}]
(-> page
keyword
vector))
(defmethod route->section :news
[{:keys [post]}]
[:news post])
(defn arrive
[{:keys [uri] :as req}]
(silk/arrive app-routes uri route->section))
(defn section->state
[[page & args]]
(match [page args]
[:news (args :guard seq)] (let [[post] args]
[:news {:post (name post)}])
[:home _] [:home {}]
[page _] [:section {:page (name page)}]))
(defn depart
[{:keys [section]}]
(let [[route params] (section->state section)]
(silk/depart app-routes route params)))
#+clj
(defn generate-response [type data & [status]]
{:status (or status 200)
:headers {"Content-Type" (condp = type
:html "text/html; charset=utf-8"
:edn "application/edn")}
:body (cond-> data
(= type :edn) pr-str)})
#+clj
(defn- ring-routes
[render]
(compojure/routes
(route/resources "/") ;; Serve static resources
(GET "*" req
(let [section (arrive req)
;; content/get-state returns state for a section.
;; you can implement either websockets or http requests for this state from the frontend
;; you could also use a .cljx file that could submit the requests. many ways of dealing with updates
state (content/get-state section)]
;; render is a server renderer similar to the one in omelette
;; https://github.com/DomKM/omelette
(generate-response :html (render state))))
(POST "/subscribe" {:keys [edn-params]}
(let [{:keys [code error]} (email/signup edn-params)]
(generate-response :edn {:success (= code 0)})))
(route/not-found "Not Found")))
#+clj
(defrecord Router [routes renderer]
component/Lifecycle
(start [this]
(assoc this
:routes (ring-routes (:render renderer))))
(stop [this]
(dissoc this :routes)))
#+clj
(defn router []
(map->Router {}))
;; used elsewhere
;; in root component did-mount
;; browser history management
;; go-aware is from https://gist.github.com/pleasetrythisathome/38717e93b09b257393a9
(.go-aware owner (browser/listen-navigation history)
(fn [token]
(let [route (router/arrive {:uri token})]
(put! (:nav chans) route))))
;; in tx-listen
(when (= :nav tag)
(let [route (router/depart new-state)]
(browser/navigate! history route)))
;; browser functions are https://gist.github.com/pleasetrythisathome/d1d9b1d74705b6771c20
;; history above created by init-history
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment