179 lines
5.9 KiB
Clojure
179 lines
5.9 KiB
Clojure
(ns core
|
|
(:require [hiccup.core :as h]
|
|
[honeysql.core :as sql]
|
|
[honeysql.helpers :refer :all :as sqlh]))
|
|
|
|
|
|
;; If using reagent you don't need to pass into h/html but this is server side
|
|
;; reagent also has some helpers to work with react nicer
|
|
|
|
|
|
(h/html [:span "bar"])
|
|
|
|
|
|
;; attributes are added as a map of values
|
|
;; styles are also a map
|
|
|
|
|
|
(h/html [:span "bar" {:class "class1 class2" :title "my title" :style {:color "red"}}])
|
|
|
|
;; you can shorthand to add id's and classes
|
|
(h/html [:span#id.class1.class2 "bar"])
|
|
|
|
;; A more complex example building a nav bar
|
|
(h/html [:header.bg-black-90.fixed.w-100.ph3.pv3.pv4-ns.ph4-m.ph5-l
|
|
[:nav.f6.fw6.ttu.tracked
|
|
[:a.link.dim.white.dib.mr3 {:href "#" :title "Home"} "Home"]
|
|
[:a.link.dim.white.dib.mr3 {:href "#" :title "About"} "About"]
|
|
[:a.link.dim.white.dib.mr3 {:href "#" :title "Store"} "Store"]
|
|
[:a.link.dim.white.dib {:href "#" :title "Contact"} "Contact"]]])
|
|
|
|
;; Obviously the main advantage comes from composing, so we can break this into function's
|
|
(defn navbar-link [{:keys [href title text] :or {text nil title nil}}]
|
|
[:a.link.dim.white.dib.mr3 {:href href :title title} text])
|
|
|
|
(defn navbar [links]
|
|
[:header.bg-black-90.fixed.w-100.ph3.pv3.pv4-ns.ph4-m.ph5-l
|
|
[:nav.f6.fw6.ttu.tracked
|
|
(map navbar-link links)]])
|
|
|
|
;; now its only a hash map and no html, in reagent you can use atom for live updating
|
|
;; notice how nil removes the attribute's so its easy to make something optional
|
|
(h/html (navbar [{:href "link1" :title "title here"}
|
|
{:href "link2" :title nil}
|
|
{:href "link3" :text "link text"}
|
|
{:href "link4"}]))
|
|
|
|
|
|
;; place parts inside another containing element
|
|
|
|
|
|
(h/html (into [:div.container] [[:span "span 1"] [:span "span 2"]]))
|
|
;; you could also use merge
|
|
(h/html (merge [:span "span 1"] [:span "span 2"] [:span "span 3"]))
|
|
|
|
;; we can take advantage of lazyness if we like
|
|
(h/html (take 2 (map navbar-link [{:href "link1" :title "title here"}
|
|
{:href "link2" :title nil}
|
|
{:href "link3" :text "link text"}
|
|
{:href "link4"}])))
|
|
|
|
|
|
;; first tip is sql/format will convert to an sql query, use it to split things up
|
|
;; in this example we create a select but with no from format will still give you a query
|
|
;; when you run the query you will get an error
|
|
|
|
|
|
(sql/format (sqlh/select :first_name :last_name :email))
|
|
|
|
;; we can join fn's together to add data
|
|
;; in this example we add the from
|
|
(sql/format (sqlh/from
|
|
(sqlh/select :first_name :last_name :email)
|
|
:users))
|
|
|
|
;; how ever it's much nicer to use the threading macro
|
|
(sql/format
|
|
(-> (sqlh/select :first_name :last_name :email)
|
|
(sqlh/from :users)))
|
|
|
|
;; ordering does not matter other than for your sanity :-)
|
|
(sql/format
|
|
(-> (sqlh/from :users)
|
|
(sqlh/select :first_name :last_name :email)))
|
|
|
|
;; we can do our usual things like limiting ordering etc
|
|
(sql/format
|
|
(-> (sqlh/select :first_name :last_name :email)
|
|
(sqlh/from :users)
|
|
(sqlh/order-by :first_name)
|
|
(sqlh/limit 10)))
|
|
|
|
(sql/format
|
|
(-> (sqlh/select :first_name :last_name :email)
|
|
(sqlh/from :users)
|
|
(sqlh/where [:= :first_name "spot"]
|
|
[:= :last_name "dog"])))
|
|
|
|
;; honey gives us a range of merge functions, below base-sql is a simple query
|
|
;; user-search extend the query replacing the selected column's and appends the where clauses if values are supplied, we could also use merge-select to extend the previous select.
|
|
;; we can use =if= =when= =when-let= =cond->= to help build these.
|
|
(def base-sql
|
|
(-> (sqlh/select :first_name :last_name :email)
|
|
(sqlh/from :users)))
|
|
|
|
(defn user-search [{:keys [first-name last-name] :or {first-name nil last-name nil}}]
|
|
(sql/format
|
|
(-> base-sql
|
|
(sqlh/select :first_name :last_name)
|
|
(sqlh/merge-where (when first-name [:= :first_name first-name]))
|
|
(sqlh/merge-where (when last-name [:= :last_name last-name])))))
|
|
|
|
(sql/format (user-search {:first-name "spot"}))
|
|
|
|
;; now is a good time to explain aliasing, basically keywords become vectors so :first_name would become [:first_name ]
|
|
(sql/format
|
|
(-> base-sql
|
|
(select [:first_name :fn] [:last_name :ln] [:email :e])))
|
|
|
|
;; extending base above we can add in an inner join statement
|
|
;; we can also alias the joined table name
|
|
(def base-join-sql
|
|
(-> base-sql
|
|
(sqlh/join [:address :a] [:= :users.address_id :a.id])))
|
|
|
|
(sql/format base-join-sql)
|
|
|
|
|
|
;; grouping by name count occurrences
|
|
|
|
|
|
(def base-group-sql
|
|
(-> base-sql
|
|
(sqlh/select :first_name [:%count.first_name :count_name])
|
|
(sqlh/group :first_name)))
|
|
|
|
(sql/format base-group-sql)
|
|
|
|
;; when all else fails you have a few options, break out =sql/raw= or extending honey sql
|
|
;; say we want to get people added in the last 14 days this is a bit more tricky
|
|
(def base-last-14-days-sql
|
|
(-> base-sql
|
|
(sqlh/where [:>
|
|
(sql/raw "created")
|
|
(sql/raw "CURRENT_DATE - INTERVAL '14' DAY")])))
|
|
|
|
(sql/format base-last-14-days-sql)
|
|
|
|
(def big-base-sql
|
|
(-> (sqlh/select :users.* :address.* :products.*)
|
|
(sqlh/from :users)
|
|
(sqlh/join :address [:= :users.address_id :address.id])
|
|
(sqlh/merge-join :products [:= :users.address_id :address.id])
|
|
(sqlh/limit 100)))
|
|
|
|
(defn big-base-filters [filters]
|
|
(-> big-base-sql
|
|
(sqlh/merge-where
|
|
(when (:first_name filters)
|
|
[:= :first_name (:first_name filters)]))
|
|
(sqlh/merge-where
|
|
(when (:last_name filters)
|
|
[:= :last_name (:last_name filters)]))
|
|
(sqlh/merge-where
|
|
(when (:product_name filters)
|
|
[:= :product.name (:product_name filters)]))
|
|
(sqlh/merge-where
|
|
(when (:active filters)
|
|
[:= :active (:active filters)]))))
|
|
|
|
(sql/format
|
|
(big-base-filters
|
|
{:first_name "spot"
|
|
:last_name "dog"
|
|
:product_name "lead"
|
|
:active true}))
|
|
|
|
|
|
|