building crud applications in clojure - meetupfiles.meetup.com/10978482/building crud applications...
TRANSCRIPT
![Page 1: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/1.jpg)
Building CRUD applications in Clojure
https://github.com/danielytics/diy-crud/
![Page 2: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/2.jpg)
What do we need?
• Request Handler
• Routing
• Database Access
• Templating
![Page 3: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/3.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Compojure, bidi, pedestal, silk, ...
Yesql, korma, lots of others for noSQL databases
Enlive, enliven, selmer, hiccup, clostache, ...
Lots of options!
![Page 4: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/4.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Bidi
Yesql
Erinite/template
![Page 5: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/5.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Bidi
Yesql
Erinite/template
Why ring?
• Defacto standard
![Page 6: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/6.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Bidi
Yesql
Erinite/template
Why bidi?
• Routes are data
• Reversible (URL -> route, route -> URL)
• Clojure and Clojurescript
![Page 7: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/7.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Bidi
Yesql
Erinite/template
Why Yesql?
• Works with JDBC
• Write SQL as SQL
![Page 8: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/8.jpg)
DIY CRUD
• Request Handler
• Routing
• Database Access
• Templating
Ring
Bidi
Yesql
Erinite/template
Why Erinite/template?
• Because I wrote it ;-)
• USP: template manipulation through data
• Will go into more detail later in this talk
![Page 9: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/9.jpg)
DIY CRUD setup a project
$ lein new crud-talk; cd crud-talk; vim project.clj
:dependencies [[org.clojure/clojure “1.7.0”]
[ring “1.4.0-RC1”]
[bidi “1.20.0”]
[yesql "0.4.0“ :exclusions [instaparse]]
[instaparse “1.4.1”] ; For clj 1.7 support
[org.xerial/sqlite-jdbc "3.7.2"]
[hiccup "1.0.5"]
[erinite/template “0.2.0”]]
:plugins [[lein-ring "0.9.6"]]
:ring {:handler crud-talk.core/handler}
![Page 10: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/10.jpg)
DIY CRUD create handler
$ vim src/crud-talk/core.clj
(ns crud-talk.core
(:require
[bidi.ring :as bidi-ring]
[yesql.core :refer [defqueries]]
[erinite.template.core :as t]
[hiccup.core :refer [html]]))
;; Other code goes here...
(def handler (bidi-ring/make-handler routes))
![Page 11: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/11.jpg)
DIY CRUD create our routes
(def routes
["/" {"items"
{{:request-method :get} read-items
{:request-method :post} create-item}
["item/" :item-id]
{{:request-method :get} read-item
{:request-method :put} update-item
{:request-method :post} delete-item
{:request-method :delete} delete-item}}])
![Page 12: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/12.jpg)
DIY CRUD create our routes
(def routes
["/" {"items"
{{:request-method :get} read-items
{:request-method :post} create-item}
["item/" :item-id]
{{:request-method :get} read-item
{:request-method :put} update-item
{:request-method :post} delete-item
{:request-method :delete} delete-item}}])
So we can test in browser without using JS
![Page 13: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/13.jpg)
DIY CRUD read a list of items
-- name: get-all-items
-- Read a summary list of all items in database.
SELECT id, name, quantity
FROM items
![Page 14: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/14.jpg)
DIY CRUD create database queries
(def db-spec {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "db.sqlite"})
(defqueries “queries.sql”)
![Page 15: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/15.jpg)
DIY CRUD create database queries
Make sure you have a database setup:
$ sqlite db.sqlite
sqlite> create table items (id int, name text, description text, qunantity int);
sqlite> insert into items values (1, ‘Test item’, ‘A test item. The first one’, 5);
sqlite> insert into items values (2, ‘Another item’, ‘A test item. The second one’, 26);
sqlite> insert into items values (3, ‘Item’, ‘The third item’, 3);
![Page 16: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/16.jpg)
DIY CRUD create template
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit"} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
![Page 17: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/17.jpg)
DIY CRUD transform template
(def item-list-transformations
{[:.items] [:clone-for :items]
[:.items :.id] [:content :id]
[:.items :.name] [:content :name]
[:.items :.quantity] [:content :quantity]
[:.items :form] [:set-attr :action :url]})
![Page 18: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/18.jpg)
DIY CRUD compile template
(def item-list
(t/compile-template
item-list-template
item-list-transformation))
![Page 19: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/19.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 20: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/20.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 21: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/21.jpg)
DIY CRUD the data
({:id 1
:name “Test item”
:quantity 5}
{:id 2
:name “Another item”
:quantity 26}
{:id 3
:name “Item”
:quantity 3})
![Page 22: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/22.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 23: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/23.jpg)
DIY CRUD the data
({:id 1
:name “Test item”
:url “/item/1”
:quantity 5}
{:id 2
:name “Another item”
:url “/item/2”
:quantity 26}
{:id 3
:name “Item”
:url “/item/3”
:quantity 3})
![Page 24: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/24.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 25: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/25.jpg)
DIY CRUD the data
{:items ({:id 1
:name “Test item”
:url “/item/1”
:quantity 5}
{:id 2
:name “Another item”
:url “/item/2”
:quantity 26}
{:id 3
:name “Item”
:url “/item/3”
:quantity 3})
![Page 26: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/26.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 27: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/27.jpg)
DIY CRUD the data
[:div {}
[:h1 {} "Item List"]
[:table {:class “items”}
[:tr {}
[:td {:class “id”} 1]
[:td {:class “name”} “Test Item”]
[:td {:class “quantity”} 5]
[:td {}
[:form {:action “/item/1” :method “post”}
[:button {:type "submit“} "delete"]]]]]
...
![Page 28: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/28.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 29: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/29.jpg)
DIY CRUD the data
<div>
<h1>Item List</h1>
<table class=“items”>
<tr>
<td class=“id”> 1</td>
<td class=“name”>Test Item</td>
<td class=“quantity”>5</td>
<td>
<form action=“/item/1” method=“post”>
<button type="submit“>delete</button>
</form>
</td>
</tr>
...
![Page 30: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/30.jpg)
DIY CRUD item list handler
(defn read-items [request]
(let [items (map
#(assoc % :url (str "/item/" (:id %)))
(get-all-items db-spec))]
{:status 200
:body (html (item-list {:items items}))}))
![Page 31: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/31.jpg)
DIY CRUD test run!
$ lein ring server
Now open localhost:3001/items
![Page 32: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/32.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit“} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
![Page 33: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/33.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit“} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
[:.items] [:clone-for :items]
![Page 34: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/34.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit“} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
[:.items] [:clone-for :items]
![Page 35: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/35.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit"} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
[:.items] [:clone-for :items]
{:items ({:id 1
:name “Test item”
:url “/item/1”
:quantity 5}
{:id 2
:name “Another item”
:url “/item/2”
:quantity 26}
{:id 3
:name “Item”
:url “/item/3”
:quantity 3})
![Page 36: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/36.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit“} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
[:.items :.id] [:content :id]
![Page 37: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/37.jpg)
DIY CRUD Erinite/template crash course
(def item-list-template
[:div
[:h1 "Item List"]
[:table.items
[:tr
[:td.id] [:td.name] [:td.quantity]
[:td [:form {:method “post”} [:button {:type "submit“} "delete"]]]]]
[:hr] [:div "New item"]
[:form#new {:action "/items“ :method "post"}
[:input.name {:type "text"}]
[:input.description {:type "text"}]
[:input.quantity {:type "text"}]
[:button {:type "submit"} "add"]]])
[:.items :.id] [:content :id]
{:id 1
:name “Test item”
:url “/item/1”
:quantity 5}
![Page 38: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/38.jpg)
DIY CRUD detour: erinite/template-stylesheets
Detour Time!
Erinite/template comes with a companion library: erinite/template-stylesheets
![Page 39: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/39.jpg)
DIY CRUD detour: erinite/template-stylesheets
Detour Time!
Erinite/template comes with a companion library: erinite/template-stylesheets
{[:.items] [:clone-for :items][:.items :.id] [:content :id][:.items :.name] [:content :name][:.items :.quantity] [:content :quantity][:.items :form] [:set-attr :action :url]}
![Page 40: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/40.jpg)
DIY CRUD detour: erinite/template-stylesheets
Detour Time!
Erinite/template comes with a companion library: erinite/template-stylesheets
{[:.items] [:clone-for :items][:.items :.id] [:content :id][:.items :.name] [:content :name][:.items :.quantity] [:content :quantity][:.items :form] [:set-attr :action :url]}
![Page 41: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/41.jpg)
DIY CRUD detour: erinite/template-stylesheets
.items {clone-for: items;
}.items .id {
content: id;}.items .name {
content: name;}.items .quantity {
content: quantity;}.items form {
set-attr: action url;}
![Page 42: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/42.jpg)
DIY CRUD detour: erinite/template-stylesheets
.items {clone-for: items;
}.items .id {
content: id;}.items .name {
content: name;}.items .quantity {
content: quantity;}.items form {
set-attr: action url;}
Now your designers can update yourtemplate transformation selectors!
![Page 43: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/43.jpg)
DIY CRUD deleting items
-- name: delete-item!
-- Delete a specific item from the database.
DELETE FROM items
WHERE id = :id
![Page 44: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/44.jpg)
DIY CRUD deleting items
(defn delete-item [request]
(let [item-id (get-in request
[:route-params :item-id])]
(delete-item! db-spec item-id)
{:status 302
:headers {"Location" "/items"}}))
![Page 45: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/45.jpg)
DIY CRUD deleting items
(defn delete-item [request]
(let [item-id (get-in request
[:route-params :item-id])]
(delete-item! db-spec item-id)
{:status 302
:headers {"Location" "/items"}}))
![Page 46: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/46.jpg)
DIY CRUD create our routes
(def routes
["/" {"items"
{{:request-method :get} read-items
{:request-method :post} create-item}
["item/" :item-id]
{{:request-method :get} read-item
{:request-method :put} update-item
{:request-method :post} delete-item
{:request-method :delete} delete-item}}])
![Page 47: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/47.jpg)
DIY CRUD deleting items
(defn delete-item [request]
(let [item-id (get-in request
[:route-params :item-id])]
(delete-item! db-spec item-id)
{:status 302
:headers {"Location" "/items"}}))
![Page 48: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/48.jpg)
DIY CRUD deleting items
(defn delete-item [request]
(let [item-id (get-in request
[:route-params :item-id])]
(delete-item! db-spec item-id)
{:status 302
:headers {"Location" "/items"}}))
![Page 49: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/49.jpg)
DIY CRUD
...and so on for create and update.
![Page 50: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/50.jpg)
Where to next?
Liberator
Define resources as conditions and actions in a state machine.
Very flexible
Makes it easy to be RFC compliant
But is lower level than I’d like
![Page 51: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/51.jpg)
Where to next?
Yada
JUXT’s new Liberator competitor
Simpler and higher level than Liberator
Built-in swagger support
![Page 52: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/52.jpg)
Where to next?
Erinite/crud
There is no good out-of-the-box CRUD library than I know of. So I plan on making one.
https://github.com/Erinite/crud
![Page 53: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/53.jpg)
Where to next?
Erinite/crud
Doesn’t exist yet, so I’m taking feature requests
![Page 54: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/54.jpg)
Where to next?
Erinite/crud
The plan so far:
• Support any database (by implementing a protocol)
• Data-driven handlers (you define your resources as data, library does the rest)
• Just a handler, so you can mount it at any route you want
![Page 55: Building CRUD applications in Clojure - Meetupfiles.meetup.com/10978482/Building CRUD applications in Clojure.pdf · •Defacto standard. DIY CRUD •Request Handler ... Erinite/template](https://reader035.vdocuments.net/reader035/viewer/2022070710/5ec5610f90b87c213c1a1691/html5/thumbnails/55.jpg)
Questions?