Trying to load a particular template based on what :server-name returns in the request:
(ns rosay.views.common
(:use noir.core)
(:require [noir.request :as req]
[clojure.string :as string]
[net.cgrand.enlive-html :as html]))
(defn get-server-name
"Pulls servername for template definition"
[]
(or (:server-name (req/ring-request)) "localhost"))
(defn get-template
"Grabs template name for current server"
[tmpl]
(string/join "" (concat [(get-server-name) tmpl])))
(html/deftemplate base (get-template "/base.html")
[]
[:p] (html/content (get-template "/base.html")))
It works for localhost which returns /home/usr/rosay/resources/localhost/base.html, but when I test against a different host say "hostname2" I see where get-template is looking at /home/usr/rosay/resources/hostname2/base.html but when it renders in the browser it always points back to ../resources/localhost/base.html.
Is there a macro or different way to handle this use-case?
As mentioned in the comments, deftemplate
is a macro that defines the template as a function in your namespace - only once, when it's first evaluated. You can easily write some code to lazily create the templates, and eliminate some of the overhead by caching the template once it's created:
(def templates (atom {}))
(defmacro defservertemplate [name source args & forms]
`(defn ~name [& args#]
(let [src# (get-template ~source)]
(dosync
(if-let [template# (get templates src#)]
(apply template# args#)
(let [template# (template src# ~args ~@forms)]
(swap! templates assoc src# template#)
(apply template# args#)))))))
In your case you'd then be able to say (defservertemplate base "/base.html"...
.
You can probably tidy this up a bit. All you really need to know is that deftemplate
just calls template
, and you can use that directly if you want.