jayunit100
jayunit100

Reputation: 17648

Dynamically adding routes in compojure

Hi guys : I have a "hierarchichal" styled site in compojure with a defroutes declaration like so :

(defroutes main-routes
  (GET "/" [] (resp/redirect "/public/index.html")
  (GET "/blog" [] (resp/redirect "/public/blogs/index.html")
  (GET "/tools" [] (resp/redirect "/public/tools/index.html"))

I would like, however, for these pages to be more dynamic - that is, I would like the index.html page to be generated by scanning the contents of the /blog directory, and likewise, for the /tools route.

That is, in the end, I would like the routes to look like so :

(defroutes main-routes
      (GET "/" [] (resp/redirect "/public/index.html")
      (GET "/blog" [] (generate-index "/public/blog"))
      (GET "/tools" [] (generate-index "/public/tools")))

Is there a simple roadmap for building dynamic paths through my site via compojure ?

More concretely ---- are there any suggestions on how to build a (generate-index) function which scans the inputted path and returns links to all files ? I assume that compojure might already have such a feature, given the recent rise of so many blogging platforms which are based on this type of idiom.

Upvotes: 2

Views: 1543

Answers (1)

deterb
deterb

Reputation: 4014

Doing most of what you said is fairly simple.

There are two things that you are going to want to look at in particular, as well as some general reading which will help you understand what's going on.

First, you are going to want to take a look at some form of HTML Templating tool. While it is possible to just build the necessary strings, things will be simpler if you use one. I've seen two different main styles for them, and which to chose depends on your tastes.

  • Hiccup is focused on taking Clojure data structures and transforming them into HTML
  • Enlive is focused on taking HTML template files and transforming them into the correct end form

For actually getting the list of files, consider using file-seq. Transform the file name into the appropriate post name and file, and then use that as data to generate the links to the pages.

The other thing you're going to want to learn more about is Compojure route templates and a little more on Ring Responses.

Compojure's route templates make it easy to pass in route parameters which you can then generate responses from. Following this is a simple example which serves a simple static html file using the html page name as the parameter.

(GET "/blog/:post" [post] (ring/file-response (str "/public/blogs/" post ".html")))

Finally, consider reading through the rest of the Compojure and Ring wikis. The Ring wiki gives some very good information on the core "how things work". The Compojure wiki provides some good examples on how to best make use of Compojure, which just focuses on providing an easy way - but far from the only way - to handle the routes and make the page generation for Ring easy.

Depending on where you want the site to go, I'd also consider taking a look at Noir, which is a framework that does a nice job at pulling together all the pieces and solving some common problems in the process.

Upvotes: 1

Related Questions