Utilities for Stuart Sierra's Component
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
compojure
httpkit
jdbc
ring
.gitignore
.travis.yml
LICENSE
README.md
project.clj

README.md

ru.prepor.component

Travis status

This is a collection of small utilities for integration of different libraries with component.

Clojars Project Clojars Project Clojars Project Clojars Project Clojars Project

Usage

ring

Ring handlers can be defined as components with attached dependencies information.

(require '[ru.prepor.component.ring :refer [defhandler with-app]]
         '[com.stuartsierra.component :as component])

(defrecord Greeting [msg])

(defhandler HelloWorld [greeting]
  (fn [req]
    (when (= "/" (:uri req))
      {:status 200
       :headers {"Content-Type" "text/html"}
       :body (str (:msg greeting) ", " (-> req :params :name))})))

Once started, this component can be can be used as usual ring handler.

(def handler (-> (assoc HelloWorld :greeting (->Greeting "Hello"))
                 (component/start )))

(handler {:request-method :get
          :uri "/"
          :params {:name "Andrew"}})
;; => {:status 200, :headers {"Content-Type" "text/html"}, :body "Hello, Andrew"}

Let's define one more component

(defrecord Master [name])

(defhandler API [greeting master]
  (fn [req]
    (when (= "/master" (:uri req))
      {:status 200
       :headers {"Content-Type" "text/html"}
       :body (str (:msg greeting) ", " (:name master))})))

Components can be combined into new component and attached to system-map before system started.

(def system (-> (component/system-map
                 :greeting (->Greeting "Hello")
                 :master (->Master "Ivan"))
                (with-app :app API HelloWorld)
                (component/start)))

with-app takes a keyword in system map for attaching, and a list of ring components. They will be called one by one until one returns something. And again, this can be used as usual ring handler.

((:app system) {:request-method :get
                :uri "/"
                :params {:name "Andrew"}})
;; => {:status 200, :headers {"Content-Type" "text/html"}, :body "Hello, Andrew"}

((:app system) {:request-method :get
                :uri "/master"})
;; => {:status 200, :headers {"Content-Type" "text/html"}, :body "Hello, Ivan"}

compojure

Actually this is not utility for compojure, but for schema-compojure :)

Compojure handlers are just ring handlers, you're not surprised, are you?

(defrecord Greeting [msg])

(defrecord DB [connection])

(defroutes Api [greeting]
  (context "/users" []
    (context "/:id" [[:params id :- s/Int]]
      (GET "/" [] (format "%s, %s (odd?: %s)" (:msg greeting) id (odd? id)))))
  (GET "/" [] (format "%s, world!" (:msg greeting))))

(defroutes Admin [db]
  (context "/admin" []
    (GET "/connections" [] (format "Connection status: %s" (:connection db)))))

A matcher can be defined (either) for an individual handler, routes or as a dependency for the entire system.

(def system (-> (component/system-map
                 :greeting (->Greeting "Hello")
                 :db (->DB "good connection"))
                (with-matcher coerce/string-coercion-matcher)
                (with-app :app Api Admin)
                (component/start)))

Use it!

((:app system) {:request-method :get, :uri "/"})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Hello, world!"}

((:app system) {:request-method :get, :uri "/users/5"})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Hello, 5 (odd?: true)"}

((:app system) {:request-method :get, :uri "/admin/connections"})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Connection status: good connection"}

http-kit

Now we can start a ring handler from previous examples via http-kit

(require '[ru.prepor.component.httpkit :refer [new-http-server]])

(def system (-> (component/system-map
                 :greeting (->Greeting "Hello")
                 :db (->DB "good connection")
                 :server (new-http-server {:port 8000}))
                (with-matcher coerce/string-coercion-matcher)
                (with-app :app Api Admin)
                (component/system-using {:server [:app]})
                (component/start)))

jdbc

JDBC utility combines component, jdbc and c3p0.

(require '[ru.prepor.component.jdbc :refer [new-jdbc]]
         '[clojure.java.jdbc :as jdbc]
         '[com.stuartsierra.component :as component])

(def jdbc (-> (new-jdbc {:classname "org.postgresql.Driver"
                         :subprotocol "postgresql"
                         :user "postgres"})
              (component/start)))

(jdbc/query jdbc ["SELECT 1 as test"])
;; => ({:test 1})

License

Copyright © 2014 FIXME

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.