문제

다음과 같이 시작하는 기능이 있습니다.

(defn data-one [suser]
    (def suser-first-name
       (select db/firstNames
            (fields :firstname)
            (where {:username suser})))
    (def suser-middle-name
        (select db/middleNames
            (fields :middlename)
            (where {:username suser})))
    (def suser-last-name
         (select db/middleNames
             (fields :lastname)
             (where {:username suser})))
    ;; And it just continues on and on...
        )
.

물론 나는 이것을 전혀 싫어한다.나는이 패턴이 코드 기반의 많은 영역에서 반복되며 이것을 일반화하고 싶습니다.

그래서, 나는 다음을 시작하고 시작했다 :

(def data-input {:one '[suser-first-name db/firstNames :firstname] 
                      '[suser-middle-name db/middleNames :middlename]
                      '[suser-last-name db/lastNames :lastname]})

(defpartial data-build [data-item suser]
    ;; data-item takes the arg :one in this case
     `(def (data-input data-item)
        (select (data-input data-item)
            (fields (data-input data-item))
            (where {:username suser}))))
.

여기에 몇 가지 질문이 있습니다 :

- X가 X가 알 수 없을 때 X 함수를 생성하도록 데이터 입력을 어떻게 해체 할 수 있습니까?하나의 값은 알려지지 않았으며 데이터 입력의 키의 수량이 알려지지 않았 음을 알 수 없습니다.

- 나는 이것이 매크로를 만드는 데 시간이지만, 나는 전에 결코 건설 한 적이 없기 때문에, 나는 그 아이디어에 대해 주저하고있다.

조금 맥락을주기 위해 기능은 해체 될 값을 반환해야하지만이 작품을 해결하면이 작품을 해결하면이 모든 것을 일반화 할 수 있습니다 :

(defpage "/page-one" []
    (let [suser (sesh/get :username)]       
    (data-one suser)
        [:p "Firat Name: " 
            [:i (let [[{fname :firstname}] suser-first-name]
                (format "%s" fname))]
        [:p "Middle Name: "  
            [:i (let [[{mname :emptype}] suser-middle-name]
                (format "%s" mname))]
        [:p "Last Name: " 
            [:i (let [[{lname :months}] suser-last-name]
                    (format "%s" lname))]]))
.

도움이 되었습니까?

해결책

몇 가지 제안 :

  • def 내부의 함수는 정말 불쾌한 입니다. - 전역 환경을 변경하고 모든 종류의 문제가 동시성이 발생할 수 있습니다.결과를지도에 저장하는 것이 좋습니다.
  • 여기에 매크로가 필요 없어 모든 데이터 페치가 함수 내에서 비교적 쉽게 수행 할 수 있습니다

    나는 다음과 같은 것을 제안 할 것입니다 :

    (def data-input [[:suser-first-name db/firstNames :firstname] 
                     [:suser-middle-name db/middleNames :middlename]
                     [:suser-last-name db/lastNames :lastname]])
    
    (def data-build [data-input suser]
      (loop [output {}
             items (seq data-input)]
        (if items
          (recur
            (let [[kw db fieldname] (first items)]
              (assoc output kw (select db (fields fieldname) (where {:username suser})))) 
            (next items))
          output)))
    
    .

    데이터베이스 설정이 없으므로 테스트하지는 않지만 매크로 또는 변경할 수없는 전역 없이이 작업을 수행하는 방법에 대한 아이디어를 제공합니다!

다른 팁

좋은 질문.우선 여기에 당신이 요구 한 매크로가 있습니다 :

(defmacro defquery [fname table fields ]
  (let [arg-name (symbol 'user-name)
        fname (symbol fname)]
    `(defn ~fname [~arg-name]
       (print ~arg-name (str ~@ fields)))))
.

그렇게 호출 할 수 있습니다 :

(defquery suser-first-name db/firstNames [:firstname])
.

또는지도에 모든 구성을 유지하려면 문자열이 기호 대신 첫 번째 인수로 문자열을 승인합니다.

(defquery "suser-first-name" db/firstNames [:firstname])
.


이제 다른 해결책을 추천하는 것을 꺼리지 않으면 구성을 마감 한 단일 기능을 사용하기로 선택했습니다.그런 것 :

(defn make-reader [query-configurations]
  (fn [query-type user-name]
    (let [{table :table field-names :fields} 
           (get query-configurations query-type)]
      (select table
             (apply fields field-names)
             (where {:username suser})))))

(def data-input {:firstname  {:table db/firstNames  :fields :firstname} 
                 :middlename {:table db/middleNames :fields :middlename}
                 :lastname   {:table db/lastNames   :fields :lastname}})

(def query-function (make-reader data-input))

;; Example of executing a query
(query-function :firstname "tom")
.

korma를 사용하는 또 다른 방법이 있습니다 :

;; This creates a template select from the table
(def table-select (select* db/firstNames))

;; This creates new select query for a specific field
(def first-name-select (fields table-select :firstname))

;; Creating yet another query that filters results by :username
(defn mkselect-for-user [suser query] 
  (where query {:username suser}))

;; Running the query for username "tom"
;; I fully specified exec function name only to show where it comes from.
(korma.core/exec (mkselect-for-user "tom" first-name-select)) 
.

자세한 정보는 Korma 소스를 보는 것이 좋습니다..

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top