2012-12-07 1 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"))) 

그것은 반환 localhost를 작동/집은/usr/rosay/자원/localhost/base.html하지만 다른 호스트에 대해 테스트 할 때 "hostname2"라고 말하면 get-template은 /home/usr/rosay/resources/hostname2/base.html을보고 있지만 브라우저에서 렌더링 할 때 항상 표시됩니다. ../resources/localhost/base.html을 다시 가리 킵니다.

이 유스 케이스를 처리하기위한 매크로 또는 다른 방법이 있습니까?

+0

문제는 deftemplate이 매크로이므로 컴파일시 평가됩니다. 그 시점에서 (: servername (req/ring-request)) nil이므로 "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으로 전화하는 것이고, 원할 경우 바로 사용할 수 있다는 것입니다.