This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # adventofcode (21)
- # announcements (4)
- # babashka (35)
- # beginners (36)
- # calva (76)
- # cider (16)
- # clj-kondo (24)
- # clj-on-windows (12)
- # clojure (70)
- # clojure-europe (7)
- # clojure-nl (13)
- # clojure-spec (3)
- # clojure-uk (3)
- # clojurescript (34)
- # conjure (11)
- # cursive (22)
- # datomic (30)
- # deps-new (2)
- # emacs (36)
- # fulcro (28)
- # gratitude (4)
- # honeysql (16)
- # hugsql (8)
- # introduce-yourself (5)
- # jobs (1)
- # malli (4)
- # missionary (6)
- # off-topic (129)
- # other-languages (34)
- # polylith (3)
- # reagent (9)
- # reitit (27)
- # releases (13)
- # remote-jobs (1)
- # reveal (1)
- # shadow-cljs (2)
- # tools-build (3)
- # tools-deps (18)
- # web-security (7)
- # xtdb (4)
Thanks @viebel for raising my question about associations here. Appreciate everyone's responses. Are there any public projects or sample code I might look at to better understand how a Clojurian deals with relational associations in practice? Many of the responses here strike me as reflections about how to do it better in the future rather than what is normal practice today.
Or maybe I'm avoiding the strict answer ... which is just work it out case-by-case because there isn't a packaged/conventional answer.
I think there is a more fundamental thing at play here. Rails / ORM -like solutions, although they exist, are not popular in the Clojure world. Most people like to write/use libraries and compose their solutions of these libraries. Most libraries consist of "pure" functions that receive data and return data. In the SQL world there is a library called HoneySql which allows you to construct SQL queries from Clojure data. And then you can pass that query to a database connector called clojure.java.jdbc (or next.jdbc) (which is not pure because it has to do some effect to the database). The HoneySQL library does not know about the next.jdbc library but you can compose these things together yourself. This allows for optimal flexibility but does not optimize for optimal initial setup.
clojure.jdbc exists but it has less than auspicious beginnings and it is no longer maintained. I think you meant
clojure.java.jdbc, the Contrib library. Could you edit your message please?
Not a good abbreviation, given that it exists and is a very different library 🙂
I would agree with that too 🙂
But perhaps it's good to go back to your original question and get it clear what's the actual problem statement, because that might not be clear at all. Association might refer to something else than ORM/SQL.
I think in order to ask the question properly, I should try to spike something in code. That'll make the ask more concrete.
I'm just trying to envision my first steps outside of ActiveRecord. For example, the app I'm working on has lots of relations where a Task is associated with some Container via a Location. And Containers themselves are located within Phases. If I were to port my Rails-thinking directly over, I would keep some kind of map around for Containers, some kind of map for Locations, and use IDs to look up what belongs to what all the time.
You might find this introduction useful. In Clojure world the focus is often on the entities and their attributes, less on the relation. An entity's attribute can itself be a reference to another entity https://www.youtube.com/watch?v=oo-7mN9WXTw
Wow this talk is amazing.
I guess I would write custom functions then to look up Tasks given some Container. Again, maybe I have to spike this to understand what the real question is. I guess it's more just some anxiety about bringing the wrong mental models into a new universe.
If I would make a CRUD-like app, I would do the querying in the database (since that's where it's stored) and then this returns data (immutable) which you can then display or whatever you want. request -> handler -> sql -> data -> (html | json response)
Is using SQL in the first place somehow "off" in the Clojure world? Is everyone using Datomic, or is that the domain of some special use cases?
There's a #sql channel which covers
clojure.java.jdbc (the older Contrib library) and
next.jdbc (its modern replacement), as well as SQL stuff in general. There's also channels for the #honeysql and #hugsql libraries if you choose to use those @rjs
Aha ok so at least I'm not in the wrong universe entirely.
If you would like to get started with SQL, I'd start here: https://github.com/seancorfield/next-jdbc/blob/develop/doc/getting-started.md
Perhaps go through the book Web Development with Clojure: https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/ This will teach you how to build typical web apps using commonly used libraries and patterns.
There is also a "framework" which is really more like a template composed of libraries by the same author, called luminus. This is a "guestbook" example: https://github.com/luminus-framework/guestbook
Ah, looks promising. Thanks
This is a really simplified one page example of a guestbook: https://github.com/kloimhardt/babashka-scittle-guestbook For persistence it uses a file on on disk. It's a toy example really. It runs with babashka which is a scripting environment for Clojure with fast startup time and is interpreted (doesn't support all of Clojure). Conceptually it works the same as what you would do in a production app (barring things like user management, connection pooling, etc, etc, again, toy example).
@yogthos I noticed the guestbook example hasn't been updated for a couple of years, but this is only because clojure is very stable and doesn't need updating right? ;)
more or less, I should probably update the library versions, but in terms of structure and API nothing really changed : )
Amazing that a couple year-old example can still hold like that
Or perhaps more amazing is that there are so many software development environments where that is NOT true.
A lot of ten-year-old Clojure still runs just fine 🙂 Our codebase at work spans over a decade and we hardly ever have to make changes when we update the version of Clojure (or any of the other Clojure libraries we use -- but we often find updating Java libraries breaks things!).