Fork me on GitHub
#integrant
<
2021-04-15
>
NoahTheDuke03:04:40

hey all! i'm trying out integrant in my app and it's going well enough, but i have a question that's not answered by the docs: i want access to the object created by integrant/`init-key` so i can reference it in the rest of my app. is that possible?

NoahTheDuke03:04:19

if not, should I bind the result to an atom and then (reset! state nil) in halt-key! ?

NoahTheDuke04:04:00

oh, this is the returned object from init, not init-keys. nevermind, i have figured it out

NoahTheDuke13:04:38

actually, follow up. my current app has a function connect which connects to the running mongo instance using an aero config file, and then uses defonce to create a db var with the returned mongo db connection

NoahTheDuke13:04:41

and then in the meat of the app, that db var is required and used, which assumes that the connection has been made and the var has been defined, etc

imre13:04:39

I'd avoid using defonce with integrant

馃憤 1
imre13:04:30

or to be broader, I'd avoid global defs for state with integrant

NoahTheDuke13:04:17

what is the more functional approach to write something like that?

imre13:04:01

just return the state from an init-key

imre13:04:08

and it'll be in the system map

imre13:04:40

and if your other component needs it, #ref that in the config

NoahTheDuke13:04:56

i'm sorry, i meant in a function like

(defn superusers []
  (mc/find-maps db "users" {$or [{:isadmin true}
                                 {:ismoderator true}
                                 {:tournament-organizer true}]}))

NoahTheDuke13:04:33

the current codebase is filled with functions like this, that assume the connection exists in the db var

NoahTheDuke13:04:43

is it better to pass the integrant system into all of these calls? or to assign it to a global variable and require it?

imre13:04:25

If you need a quick first pass, I'd go with the former out of those two

imre13:04:10

but you could make that fn a component itself sort of how handler/greet returns a function at https://github.com/weavejester/integrant#initializing-and-halting

NoahTheDuke13:04:25

that page doesn't load for me

imre13:04:51

apologies, wrong link

imre13:04:15

or you could make a component that returns a reify over a protocol, wrapping your db and exposing all the db-needing functions

NoahTheDuke13:04:37

hmmmm interesting!

imre13:04:01

or some groupings of functions in between one-fn-per-component and all-db-fns-in-one

imre13:04:09

that's suitable to your usecases

NoahTheDuke13:04:30

yeah makes sense

NoahTheDuke13:04:54

i'll have to think about this a bunch, see what makes most sense

imre13:04:57

the point of integrant is that you build up components that are self-contained enough so that other, dependent components only need to pass in args that are relevant to their usecases

imre14:04:10

You can eliminate most if not all global state this way as all of it will be inside the system map.

NoahTheDuke14:04:08

yeah, that's definitely the goal cuz it's a ball of spaghetti right now

imre14:04:01

hah, I've learned that not even integrant can guarantee spaghettilessness 馃槃

NoahTheDuke14:04:10

23 different namespaces require that db var, which makes it "easy" but also very messy and means we have to be careful when writing tests or running things individually

imre14:04:45

you can have one component per namespace for example

imre14:04:12

each returning something that wraps its functions, requiring the db component

NoahTheDuke15:04:47

by "wraps its functions", do you mean:

(defn example [{db :system/db}]
  (defn db-fn1 [arg]
    (do-something db arg))
  (defn db-fn2 [arg]
    (do-something db arg))
  ...)

imre15:04:53

Not really, more like:

imre15:04:03

(defn example [{db :system/db}]
 {:db-fn1 (fn [arg] (do-something db arg))
  :db-fn2 (fn [arg] (do-something db arg))})

馃憤 1
imre15:04:33

even better if you create a protocol defining the interface for fn1 2 etc

馃憤 1
imre15:04:41

and reify that within example

NoahTheDuke15:04:28

thanks for the example, that's helpful

imre15:04:13

you're welcome

NoahTheDuke14:04:51

that's a neat trick. i realize i'm asking a lot, but do you have any projects/examples of that kind of logic?

imre14:04:29

I'm afraid I don't have anything I'd be allowed to share. But integrant is a phrase specific enough that a github code search should give you some examples

NoahTheDuke14:04:19

coolio, thanks so much for the help

imre14:04:14

Nb, good luck! It takes a little getting used to but it's worth it