2013-11-04 11 views
13

링 핸들러에 상태를 가장 편리하게 주입하려면 어떻게해야합니까? 내가 main-routes의 compojure 핸들러에 the-state을 좀하고 싶습니다링 핸들러에 상태를 매개 변수로 전달 하시겠습니까?

(defroutes main-routes 
    (GET "/api/fu" [] (rest-of-the-app the-state))) 

(def app 
    (-> (handler/api main-routes))) 

: 여기

은 예입니다. 의 다른 구성 요소에 대한 기능을 매개 변수로 비 링 응용 프로그램 I는 주요 기능의 상태를 만들고 주입을 시작하거나 일부 것에서

(defn create-app-state [] 
    {:db (connect-to-db) 
    :log (create-log)}) 

: 상태가 만든지도 같은 수 있습니다 응용 프로그램.

글로벌 var를 사용하지 않고 링의 :init 기능과 비슷한 기능을 수행 할 수 있습니까?

+0

세션 별 상태 또는 전체 상태를 찾고 있습니까? – astine

+0

전역 - 같은 수명 : 초기화 및 : 파괴 – 4ZM

답변

20

나는 이것을 두 가지 방법으로 보았다. 첫 번째는 요청 맵에서 상태를 새로운 키로 주입하는 미들웨어를 사용하는 것입니다. 예를 들어 :

(defroutes main-routes 
    (GET "/api/fu" [:as request] 
    (rest-of-the-app (:app-state request)))) 

(defn app-middleware [f state] 
    (fn [request] 
    (f (assoc request :app-state state)))) 

(def app 
    (-> main-routes 
     (app-middleware (create-app-state)) 
     handler/api)) 

다른 방법이 핸들러를 생성하고 경로를 생성 한 후 몇 가지 상태를 받아들이고하는 기능을하는 VAR에 할당됩니다 뒤에서 defroutes에 대한 호출을 대체하는 것입니다, 매개 변수로 상태를 주입하면 경로 정의에서 함수 호출하기 :

(defn app-routes [the-state] 
    (compojure.core/routes 
    (GET "/api/fu" [] (rest-of-the-app the-state)))) 

(def app 
    (-> (create-app-state) 
     app-routes 
     api/handler)) 

선택의 여지를 주어

, 나는 아마 두 번째 방법으로 갈 것.

+1

감사! 두 번째 접근 방식은 적합 할 것으로 보인다. 처음에는 약간의 해킹 딱지가 느껴집니다. – 4ZM

-1

"올바른"방법은 동적으로 바인딩 된 var를 사용하는 것입니다. 당신과 함께 VAR를 정의

(def ^:dynamic some-state nil) 

그리고 당신은 각 핸들러 호출 var에 결합 일부 링 미들웨어 작성 :

(defn wrap-some-state-middleware [handler some-state-value] 
    (fn [request] 
    (bind [some-state some-state-value] 
     (handler request)))) 

당신은 당신의 주요이를 사용하여 종속성을 주입하려면이 옵션을 사용하는 것을 '기능을 사용합니다.

(def app (-> handler 
      (wrap-some-state-middleware {:db ... :log ...}))) 
+0

당신은 동적으로 많은 상태 관리를 할 것입니다. 나중에 심각한 문제가 발생할 수 있습니다. – Virmundi