After yesterday’s introduction to the syntax of clojure, now I’m going to start organizing my code a bit more and pulling in real data.
Templating
The first thing I want to do is abstract out a base page so that I don’t need to worry about headers, JS libraries, standard CSS, and all that when going from page to page. To do this, I’ll create a “page” function in a new namespace.(ns flockr.template | |
(:use compojure )) | |
(defn page | |
([title body] | |
(html [:html | |
(html [:head | |
(html [:title title]) | |
] | |
(html [:body | |
(html [:div#menu "Menu"] | |
body) | |
])) | |
]))) | |
Then I add this into our original page.
(load-file "./template.clj") | |
(ns flockr | |
(:use compojure ) | |
(:refer flockr.template)) |
Now I can call the “page” function, pass it a title and some contents, and it outputs a full page. Perhaps later on we’ll make it so we can derive templates from other templates, but I have no need for that yet.
Getting My Twitter Feed
Let’s make it so that getting “/justin_tulloss” will give me my twitter feed. To do that, I add a handler to our servlet.(GET "/:twitter-name" | |
(page "Your Flock" | |
(html [:h1 "Welcome " (route :twitter-name)]))) | |
Now when I go to http://localhost:8080/justin_tulloss, it will say “Welcome justin_tulloss”. Pretty high tech stuff.
Now let’s see if I can change that justin_tulloss parameter into my actual twitter data. First, I head over to the twitter API docs. The public timeline doesn’t require any authentication, so let’s pull that down first. The public timeline is a list of “status” messages, which we will map to html representations of the same. To do this, I used the clj-http-client library by Mark McGranaghan. It was a pain to get installed because I don’t understand Java JAR files fully, but once I got it figured out, it worked great.
(GET "/:twitter-name" | |
(page "Your Flock" | |
(html [:h1 "Welcome " (route :twitter-name)] | |
(map twitter-status | |
(read-json-string (let [[status headers body] | |
(http-get *twitter-url*)] body)))))) |
Hopefully this code isn’t hard to follow, but let’s take a look. The “Welcome” part is the same. Then we map everything that we read from the twitter URL into a twitter-status function, which just grabs some data out of the statuses and displays it.
(defn twitter-status | |
([tweet] | |
(html [:p {:class "tweet"} | |
(html [:div {:class "tweet-text"} (get tweet "text")]) | |
(html [:div {:class "tweet-user"} (get (get tweet "user") "name") ])]))) |
Referring back to the non-templating code, the “read-json-string” function is in clojure.contrib.json.read, which you can get here. The twitter-url is a global constant. Apparently it’s a lisp thing to surround globals with asterisks. I wonder if that also applies to global constants.
(def *twitter-url* "http://twitter.com/statuses/public_timeline.json") |
Well, that’s all for tonight. Next time we’ll fetch some more relevant data from twitter and see what we can do with it. As always, the complete code is on github.