11 ms·
Here's a quick example of how DB access generally looks in production: (ns rads.sql-example (:require [next.jdbc :as jdbc] [honey.sql
by rads 2y ago
Here's a quick example of how DB access generally looks in production:
(ns rads.sql-example
(:require [next.jdbc :as jdbc]
[honey.sql :as sql]
[clojure.string :as str]))
;; DB Table: posts
;; +----+-------+
;; | id | title |
;; +----+-------+
;; | 1 | hello |
;; +----+-------+
(def ds (jdbc/get-datasource (System/getenv "DATABASE_URL")))
(defn row->post [row]
;; This is your optional mapping layer (a plain function that takes a map).
;; You can hide DB details here.
(update row :title str/capitalize))
(defn get-posts [ds]
;; Write a SQL query using Clojure data structures.
(let [query {:select [:*] :from [:posts]}]
;; Run the query.
(->> (jdbc/execute! ds (sql/format query))
;; Convert each raw DB map to a "post" map
(map row->post))))
(println (get-posts ds))
;; => [{:id 1, :title "Hello"}]
- winrid 2y agoYou would abstract away the jdbc/execute part though, right? otherwise that's terribly unproductive compared to django etc.
- rads 2y agoIn practice I do wrap `jdbc/execute!` with my own `execute!` function to set some default options. However, there is no ORM layer. What makes you think the code above is terribly unproductive? Edit: Not trying to dismiss your concerns, by the way. In Clojure you can often get away with doing less than you might think so I'm genuinely curious about the critique.
- winrid 2y agoIn Django I would just do Posts.objects.filter(title=x) I don't need to define driver boilerplate for every query (or ever have to write it... at all).
- rads 2y agoThe key thing is experienced Clojure programmers often see a lack of ORM as a feature rather than an oversight. There were some more ORM-like libraries years ago (see Korma) but my impression is that people ultimately didn't want this and moved on to lower-level JDBC wrappers combined with HoneySQL. I found a more detailed discussion on Reddit about Clojure and ORMs back in 2020 if you want to get more info: https://reddit.com/r/Clojure/comments/g7qyoy/why_does_orm_have_omg_complexity/ https://reddit.com/r/Clojure/comments/g7qyoy/why_does_orm_ha... Note that I'm not making a value judgement about Python/Django or any other library/framework combination. It's obviously a valid path, but Clojure is a different path. I can assure you there are straightforward solutions to create readable APIs like the Django example with minimal boilerplate, but the approach is fundamentally different from Python/Django. If you do decide to build something in Clojure and think, "I already know how to do this in Django, why is it missing?", don't hesitate to join the Clojurians Slack and hop into the #beginners channel. There are plenty of people who can help you there.
- didibus 2y agoIn Clojure you'll have to write the queries yourself unfortunately. People always ask, where is the fully fledged web framework in Clojure? There isn't one. Why there isn't one is hard to answer, but it's partially because the people who could write one, don't find they need one themselves. There's definitely a preference in Clojure for not relying on frameworks, because the current people in the community like to be in control, know what's going on, or do it their own way. That said, the whole code still ends up being relatively small. So, you kind of end up with a similar amount of total code, but you're much more in control. And if certain things you find too repetitive, you can remove the repetition yourself through many of Clojure's facilities, specifically where they annoyed you. See: https://github.com/didibus/simple-website-with-posts https://github.com/didibus/simple-website-with-posts where I implemented the small website you were talking about, creating posts and seeing them. The whole code is here (minus the CSS): https://github.com/didibus/simple-website-with-posts/blob/main/src/com/github/didibus/simple_website_with_posts.clj https://github.com/didibus/simple-website-with-posts/blob/ma... It's 95 loc and that includes the templates. There's no framework.
- 2y ago