Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Apps on a Pedestal

Web Apps on a Pedestal

Learn how to build web applications in Clojure using the Pedestal library.



Ryan Neufeld

April 17, 2014

More Decks by Ryan Neufeld

Other Decks in Programming


  1. Web Apps on a Pedestal

  2. @rkneufeld – rkn.io Ryan Neufeld

  3. None
  4. None
  5. Pedestal > Ring

  6. Nailed Down

  7. Flying Free

  8. Enter the workshop

  9. Todo-it

  10. Demo project-building time

  11. [“/hello” {:get hello-world}] ! Handler map Path pattern Anatomy Lesson:

  12. [“/hello” {:get hello-world} child-routes…] Anatomy Lesson: Children [“/“ [“/hello” {:get

  13. [[[“/“ [“/hello” {:get hello-world}]]]] Why so nested?

  14. [[context routes…]] ! “hello” route App name, port, host Anatomy

    Lesson: Context
  15. [[:public “example.com” routes…] [:api “api.example.com” routes…]] Anatomy Lesson: Contexts

  16. Demo project-building time part ii

  17. Exercise #1 1. Install Leiningen (http:/ /leiningen.org/#install) 2. git clone

    https:/ /github.com/rkneufeld/pedestal-workshop 3. Checkout exercise-1 4. Run the app w/ lein run 5. Visit localhost:8080/hello 6. Change “Hello, World!” to “Hello, <your name>!”* *You’ll need to restart the server
  18. Demo routes & interceptors

  19. No Handler is an Island

  20. It takes a village* *Of middleware and handlers OK, doesn’t

    have the same ring to it… Enter from left to right Leave from right to left
  21. Anatomy Lesson: Interceptors

  22. Anatomy Lesson: Interceptors

  23. Anatomy Lesson: Interceptors

  24. Routers are Interceptors

  25. Where they live (def service {::http/interceptors [… (router routes)]…} Before

    or after routing
  26. [[[“/” ^:interceptors […] [“/hello” {:get hello-world] [“/goodbye” …]]] Where they

    live Inside routes
  27. [[[“/“ [“/hello” {:get hello-world] [“/goodbye” …]]] Where they live Inside

    routes * * *Attachment points *
  28. Demo routes & interceptors

  29. Exercise #2 1. Checkout exercise-2 2. Restart your server w/

    lein run 3. Visit localhost:8080/hello?name=<yours name> 4. Use the (or x y) form to provide "World" as a default name if none is provided. 5. Bonus: Write a defon-response interceptor that changes :header’s "Server" key to something unique of your choosing.
  30. A little persistence

  31. A little persistence

  32. MVC* CRUD

  33. MVC* CRUD

  34. Demo A lil’ persistence

  35. Exercise #4 1. Checkout exercise-4 2. Launch a REPL w/

    lein repl 3. Require and enter todoit.todo.db • (require 'todoit.todo.db) • (in-ns 'todoit.todo.db) 4. Create, Read, Update, then Destroy a TODO • Get a db value with (d/db conn) 5. Bonus: Write a query completed-todos that ensures [?id :todo/completed? true]
  36. Demo Wiring up C & R

  37. Exercise #5 1. Checkout exercise-5 2. Try out /todos 3.

    Implement and wire-up a create function in todo.clj Hint: Use let à la hello-world to extract [:form-params “title”] and [:form-params “description”]. Once you’ve created a TODO, redirect to (url-for :todos).
  38. New Paint Job

  39. Demo New Paint Job

  40. Hiccup [:tag {attributes} children] required optional optional .class #id optional

  41. Hiccup <h1>The Title</h1> ! <div class=“foo”> <p>Great content</p> </div> !

    <form action=“/todos” method=“post”> <input name=“title” /> </form> [:h1 “The Title”] ! [:div.foo [:p “Great Content”]] ! ! [:form {:action “/todos” :method “post”} [:input {:name “title”}]
  42. Demo New Paint Job

  43. Exercise #6 1. Checkout exercise-6 2. Try out the new

    /todos 3. Add a TODO without a title. Oops! 4. Modify the TODO form’s title to be required (hint, the required attribute).
  44. Demo Update & Destroy

  45. Exercise #7 1. Checkout exercise-7 2. Try out toggling and

    deleting TODOs 3. Create a delete-all action. You’ll need a: • Route, • Handler, • Model Action, and • Form
  46. Questions? bit.ly/pedestal-ws @rkneufeld Photo credits: https:/ /flic.kr/p/bE6KtD, https:/ /flic.kr/p/9p4utz pedestal.io