Domanda

Ho una funzione che inizia così:

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

Certo, non mi piace affatto.Ho questo motivo ripetendo in molte aree nella mia base di codice e mi piacerebbe generalizzare questo.

Allora, sono venuto con il seguente per iniziare:

(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}))))
.

Ci sono davvero alcune domande qui:

- Come posso decostruire l'ingresso dati in modo che crea funzioni x quando x è sconosciuta, cioè.che i valori di: uno è sconosciuto e che i quantitativi di chiavi nell'ingresso dati non sono sconosciuti.

- Sto pensando che questo sia un momento per creare una macro, ma non ne ho mai costruito uno prima, quindi sono esitante sull'idea.

E per dare un piccolo contesto, le funzioni devono restituire i valori per essere decostruiti, ma penso che una volta ottenuto questo pezzo risolto, generalizzando tutto questo sarà fattibile:

(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))]]))
.

È stato utile?

Soluzione

Alcuni suggerimenti:

    .
  • def all'interno di una funzione è realmente brutto - stai alterando l'ambiente globale e può causare tutti i tipi di problemi con la concorrenza.Suggerirei di memorizzare i risultati in una mappa invece.
  • you non hai bisogno di una macro qui - Tutti i dati dei dati possono essere eseguiti relativamente facilmente all'interno di una funzione

    Suggerisco quindi qualcosa come:

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

    Non testato come non ho il tuo set-up del database - ma si spera che ti dà un'idea di come farlo senza macro o globali mutabili!

Altri suggerimenti

Nice domanda.Prima di tutto ecco la macro che hai chiesto:

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

Puoi chiamarlo in quel modo:

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

O se preferisci mantenere tutte le configurazioni in una mappa, accetterà la stringa come primo argomento anziché un simbolo:

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


.

Ora, se non ti dispiace che mi raccomanda un'altra soluzione, probabilmente avrei scelto di utilizzare una singola funzione chiusa attorno alla configurazione.Qualcosa del genere:

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

A proposito c'è un altro modo per usare 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)) 
.

Per ulteriori informazioni consiglio vivamente di guardare a fonti Korma.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top