SORU
15 AĞUSTOS 2010, Pazar


's "fikir" compojure yolları arkasında?

Clojure yeniyim ve Compojure temel bir web uygulaması yazmak için kullanmışlardır. Compojure ile bir duvar defroutes sözdizimi olsa da, her ikisi de anlamak lazım diye düşünüyorum "nasıl" ve "neden" her şeyin arkasında. basıyorum

Göründüğü gibi bir Yüzük tarzı bir uygulama ile başlayan bir HTTP isteği göster, o zaman sadece geçer isteği ile bir dizi katman işlevleri kadar alır dönüştürülmüş bir tepki göster, hangi alır geri gönderilen tarayıcı. Bu tarzı da "seviye" geliştiriciler için, böylece bir araç ihtiyacı Compojure gibi. düşük görünüyor Özellikle Python'un WSGI ile diğer yazılım ekosistemlerinde daha soyut bu da görebiliyorum.

Sorun Compojure yaklaşımı anlamıyorum. Hadi 10 ** S-ifade şu:

(defroutes main-routes
  (GET "/"  [] (workbench))
  (POST "/save" {form-params :form-params} (str form-params))
  (GET "/test" [& more] (str "<pre>" more "</pre>"))
  (GET ["/:filename" :filename #".*"] [filename]
    (response/file-response filename {:root "./static"}))
  (ANY "*"  [] "<h1>Page not found.</h1>"))

Tüm bunları anlamanın anahtarı bazı makro voodoo içinde olduğunu biliyorum, ama tamamen makrolar (henüz) anlamıyorum. Uzun bir süre defroutes kaynağına baktım, ama sadece alamadım! Burada neler oluyor? Anlayış "büyük fikir" muhtemelen bana cevap yardımcı olacak bu özel sorular:

  1. Nasıl yönlendirilen bir işlev içinde Halka ortamı (örneğin workbench işlevi) erişebilirim? Örneğin, HTTP_ACCEPT başlıkları veya isteği başka bir bölümüne erişim için/katman istedim ki?
  2. Bu destructuring ({form-params :form-params}) ile anlaşma nedir? Anahtar kelimeler destructuring zaman benim için vardır.

Gerçekten Clojure gibi ama tıkandım!

CEVAP
16 AĞUSTOS 2010, PAZARTESİ


Compojure açıkladı (bir dereceye kadar)

NB. Compojure 0.4.1 (here'In 0.4.1 sürümü commit GitHub). ile çalışıyorum

Neden?

compojure/core.clj, çok üstünde Compojure amacı bu yararlı Özet var:

Kısa ve öz bir Yüzük işleyicileri oluşturmak için sözdizimi.

Yüzeysel bir düzeyde, hepsi bu var "neden" sorusu. Biraz daha derine gitmek, hadi bir tarzı Yüzük fonksiyonları uygulama nasıl bir göz atın:

  1. Bir talep geldi ve Halka spec uyarınca Clojure bir harita dönüşür.

  2. Bu harita sözde içine akıttığını "işleyici işlevi bir tepki de Clojure bir harita olan) üretmesi bekleniyor.",

  3. Tepki göster gerçek bir HTTP yanıtı dönüşür ve geri istemciye gönderilen.

Adım 2. yukarıdaki en ilginç işleyicisi var URI isteğinde kullanılan incelemek için sorumluluk, vb herhangi bir kurabiye inceleyin. ve sonuçta uygun bir yanıt gelmesi. Bütün bu çalışmalar İyi tanımlanmış parçalar; bu normal bir koleksiyon hesaba katılması gereklidir açıkça bir "temel" işleyici fonksiyonu ve katman işlevlerini kaydırma koleksiyonu.Compojure amacı temel işleyici işlevi üretimi kolaylaştırmak için.

Nasıl?

Compojure kavramı etrafında inşa edilmiştir "yolları". Bu aslında Clout kütüphane şeyler 0.3 ayrı kütüphaneler taşındı çok. (Compojure projenin bir yan tarafından derin bir düzeyde uygulanmasını x ->0.4.x geçiş). Bir rota tanımlanır (1) HTTP metodu (GET, PUT, HEAD...), (2) bir URİ desen (belirtilen sözdizimi olacak anlaşılan bildik gelecek Webby Rubyists), (3) bir destructuring formu kullanılan bağlayıcı parçaların talep harita isimleri mevcut bulunan cesedin, (4) bir vücut ifadesi olan ihtiyaçlara üretmek geçerli bir Yüzük yanıt (önemsiz olmayan durumlarda bu genellikle sadece bir çağrı için ayrı bir fonksiyon).

Bu basit bir örnek bakmak için iyi bir nokta olabilir:

(def example-route (GET "/" [] "<html>...</html>"))

Hadi istek aşağıdaki harita minimal geçerli Halkası istek göster) ÇOĞALTMA de bu test:

user> (example-route {:server-port 80
                      :server-name "127.0.0.1"
                      :remote-addr "127.0.0.1"
                      :uri "/"
                      :scheme :http
                      :headers {}
                      :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "<html>...</html>"}

:request-method :head yerine olsaydı, yanıt nil olurdu. nil bir dakika içinde burada (ama geçerli bir Yüzük respose değil dikkat edin!) ne demek soru dönüyoruz.

Olduğu gibi görünen bu örnek, example-route sadece bir fonksiyon, ve bir çok basit biri; bakıyor isteği olup olmadığını belirler. ilgilendiği işleme (tarafından incelenmesi :request-method :uri) ve, eğer öyleyse, döner bir temel tepki göster.

Ne olduğu da belli, bu yüzden yol değil gerçekten ihtiyacı değerlendirmek için uygun bir tepki göster; Compojure sağlar aklı başında varsayılan kullanım için dizeleri (olarak görülen yukarıda) ve bir dizi diğer nesne türleri; compojure.response/render multimethod için Ayrıntılar (kod tamamen kendi kendine tanım burada).

Hadi defroutes kullanarak şimdi deneyin:

(defroutes example-routes
  (GET "/" [] "get")
  (HEAD "/" [] "head"))

:request-method :head ile onun bir türevi için örnek istek üzerinde görüntülendiğini ve yanıtları gibi bekleniyor.

İç yapısı example-routes gibi her yolu denedim sırayla; en kısa sürede birini döndürür olmayannil tepki, yanıt olur dönüş değeri, bütün example-routes işleyicisi. Ek bir kolaylık, *32 tanımlı*olarak işleyicileri wrap-params wrap-cookies örtülü olarak sarılır.

Burada daha karmaşık bir rota bir örnek:

(def echo-typed-url-route
  (GET "*" {:keys [scheme server-name server-port uri]}
    (str (name scheme) "://" server-name ":" server-port uri)))

Daha önce kullanılan boş vektör yerine destructuring formu unutmayın. Burada temel fikir, bu yüzden yol olabilir ilgilendiği hakkında bilgi isteği; beri bu hep gelir şeklinde bir harita, bir ilişkisel destructuring form temin edilebilir ayıklamak için bilgi isteği ve bu büyüyü yapmak için yerel değişkenler çıkar kapsamı, güzergahı cesedini.

Yukarıda bir test:

user> (echo-typed-url-route {:server-port 80
                             :server-name "127.0.0.1"
                             :remote-addr "127.0.0.1"
                             :uri "/foo/bar"
                             :scheme :http
                             :headers {}
                             :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "http://127.0.0.1:80/foo/bar"}

Parlak takibi yukarıda fikir daha karmaşık yollar 37 ** eşleştirme aşamasında istek üzerine ek bilgiler olabilir

(def echo-first-path-component-route
  (GET "/:fst/*" [fst] fst))

Bu önceki örnekte isteği "foo" :body ile yanıt verir.

Bu son örnek yeni olan iki şey: "/:fst/*" ve boş olmayan bağlayıcı vektör [fst]. İlk Rayları-ve-Sinatra-URİ desen sözdizimi söz konusu. Biraz daha sofistike, daha ne olduğu belli gelen yukarıdaki örnekte bu düzenli ifade kısıtlamaları URI parçası desteklenir (örneğin ["/:fst/*" :fst #"[0-9] "] temin edilebilir yapmak için rotayı kabul sadece bir basamak değerleri :fst yukarıda). İkinci basit bir şekilde eşleşen :params giriş isteğini göster, kendini bir göster; bu yararlı için açılan URİ kesimlerinden isteği sorgu dizesi parametreleri ve form parametreleri. İkinci bir örnek göstermek için:

(defroutes echo-params
  (GET "/" [& more]
    (str more)))

user> (echo-params
       {:server-port 80
        :server-name "127.0.0.1"
        :remote-addr "127.0.0.1"
        :uri "/"
        :query-string "foo=1"
        :scheme :http
        :headers {}
        :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "{\"foo\" \"1\"}"}

Bu soruyu metni: örnek bakmak için iyi bir zaman olabilir

(defroutes main-routes
  (GET "/"  [] (workbench))
  (POST "/save" {form-params :form-params} (str form-params))
  (GET "/test" [& more] (str "<pre>" more "</pre>"))
  (GET ["/:filename" :filename #".*"] [filename]
    (response/file-response filename {:root "./static"}))
  (ANY "*"  [] "<h1>Page not found.</h1>"))

Hadi sırayla her rota analizi:

  1. :uri "/" ile GET isteği ile uğraşırken (GET "/" [] (workbench)) -- fonksiyonu workbench çağrı ve yanıt bir harita haline döndürdükleri kılıyor. (Dönüş değeri bir harita, aynı zamanda, bir dize vb olabilir hatırlayın.)

  2. (POST "/save" {form-params :form-params} (str form-params)) -- :form-params isteği wrap-params katman tarafından sağlanan göster (örtülü olarak defroutes dahil olduğunu hatırlayın) bir giriştir. Yanıt (str form-params) 56 *standart ... yerine olacaktır. (Biraz sıradışı POST bir işleyici, bu...)

  3. (GET "/test" [& more] (str "<pre> more "</pre>")) -- bu, örneğin, eğer kullanıcı Aracısı "/test?foo=1" istenirse harita {"foo" "1"} dize gösterimini geri echo.

  4. (GET ["/:filename" :filename #".*"] [filename] ...) -- :filename #".*" part hiçbir şey #".*" her zaman eşleşir). Zil programı ring.util.response/file-response yanıt üretmek için fonksiyonu çağırır; {:root "./static"} bölüm dosyası için nereye bakmam gerektiğini söyler.

  5. (ANY "*" [] ...) -- -tüm yakalamak rota. İyi Compojure uygulama her zaman için vardır böyle bir rota sonunda defroutes form sağlamak için işleyici olarak tanımlanan her zaman döndürür geçerli bir Halka tepki göster (hatırlama bir yol eşleşen başarısızlık sonuçları nil).

Neden bu şekilde?

Tek bir amaç Halka katman Ekle bilgi isteği göster; böylece çerez işleme katman ekler :cookies anahtar isteği, wrap-params ekler :query-params ve/veya :form-params eğer bir sorgu dizesi / form veri mevcut. (Doğrusu, tüm bilgilerin katman fonksiyonlar ekleyerek olmalı zaten mevcut isteğini göster, beri ne olsun geçti; onların iş için dönüştürmek için daha rahat çalışma ile işleyicileri onlar sarın.) Sonuçta" istek güzel önişlenmiş tüm bilgileri katman tarafından eklenmiş göster ve bir yanıt üretir inceleyen temel işleyicisi geçirilir. "zenginleştirilmiş (Katman -- birkaç "" vb. tüm işleyicileri ve aralarında seçerek, sarılmış işleyicisi çağırmak için karar verirken(s) iç sarma gibi daha karmaşık şeyler yapabilir Ancak, bu cevap kapsamı dışındadır.)

Temel işleyici, sırayla, genellikle (önemsiz olmayan durumlarda) isteği hakkında bilgi sadece bir avuç öğeleri ihtiyacı olan eğilimi olan bir işlevdir. (E. g. ring.util.response/file-response istek çoğu umursamıyor, sadece bir dosya adı gerekir.) Halka bir istek sadece ilgili bölümlerini ayıklamak için basit bir yol için böylece gerek. Compojure yok sadece hangi amaçlı özel desen eşleştirme motoru olarak sunmayı amaçlıyor.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Alan Fullmer

    Alan Fullmer

    3 EYLÜL 2010
  • Rhapsody

    Rhapsody

    7 ŞUBAT 2008
  • Video Copilot

    Video Copilo

    21 EYLÜL 2006