2012-12-07 26 views
4

試圖基於什麼加載特定的模板:在請求服務器名稱返回:的Clojure,enlive,多站點

(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"))) 

它適用於本地主機返回/主頁的/ usr /羅賽/資源/ localhost/base.html,但是當我測試一個不同的主機時會說「hostname2」,我看到get-template在/home/usr/rosay/resources/hostname2/base.html中的位置,但是當它在瀏覽器中呈現時,它始終指向../resources/localhost/base.html。

有沒有宏或不同的方式來處理這種用例?

+0

問題是deftemplate是一個宏,所以它在編譯時進行評估。此時(:servername(req/ring-request))爲零,因此「localhost」將被硬編碼到爲您的視圖生成的類文件中。 –

+0

因此,與irc上的某些人交談時,他們提到了使用'at'的可能性,但是,由於在每個請求中重新編譯模板,因此存在一些性能方面的考慮因素 – battlemidget

回答

2

正如在評論中提到的,deftemplate是一個宏,它將模板定義爲函數在您的命名空間中 - 只有一次,當它第一次評估。你可以很容易地編寫一些代碼來創建懶洋洋的模板,以及一旦它的創建緩存模板消除一些開銷:

(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 [email protected])] 
      (swap! templates assoc src# template#) 
      (apply template# args#))))))) 

在你的情況下,你再能說(defservertemplate base "/base.html"...

你也許可以整理一下。您真正需要知道的是deftemplate只需撥打template,如果您願意,您可以直接使用它。