Fork me on GitHub
#clojure
<
2022-12-28
>
Flash Hu06:12:12

What better way to build a database connection with Korma in a Pedestal project with Omniconf? I’m building up an API server with Postgres as Database. With the help of Omniconf, I want to override the Database configuration during dev, staging and production. I found I had to define the connection after I loaded configurations with Omniconf, and then I came up with a solution below:

;; server.clj of Pedestal
(defn run-dev  
  "The entry-point for 'lein run-dev'"  
  [& args]  
  (println "\nCreating your [DEV] server...")  

;; initialize configuration with Omniconf
  (cfg/init-config {:cli-args args})  

;; define a database connection with Korma
  (defdb db  
       (postgres {:db       (cfg/get-config :db-name)  
                  :user     (cfg/get-config :db-user)  
                  :password (cfg/get-config :db-pass)}))
  ;; ... other functions                  
Is there any better way to do this?

devn19:12:27

Maybe? Probably? I haven’t worked with korma or pedestal, but the gist of your problem is basically that defdb expects your configuration to be available when it is compiled. You could just manually do the steps it’s doing inside a function that you call once you know your config is ready.

(defn db-spec []
  {:db (cfg/get-config :db-name) ...})

(defn make-db []
  (defonce db (korma.db/create-db (postgres (db-spec))))
  (korma.db/default-connection db))
Then call make-db after configuration has been loaded.

❤️ 1
Flash Hu02:12:06

Thanks again for the detailed hints. I’m unfamiliar with macros, as I’m still new to Clojure. I guess that’s why I came into this issue when using defdb. I refactor my code with your suggestions, and it looks better now 🙂 , as I can easily reuse it in both endpoints (dev and production) and reduce typos.

👍 1
ghadi14:12:49

The better way is not to use Korma. It’s a very problematic library, partly because the db argument isn’t an argument but ambient global state.

1
💯 1
Flash Hu01:12:50

Could you suggest any other library to handle DB with? Or It’s better to use the basic clojure.java.jdbc library?

ghadi01:12:28

absolutely. Pass the db as an argument

ghadi01:12:51

next.jdbc is the library to use, with honeysql to compose queries if desired

Flash Hu01:12:18

Thanks! I’ll take a look into them

Madara Uchiha16:12:09

I have the following multimethod:

(defmulti compare-part (fn [left right] [(coll? left) (coll? right)]))
(defmethod compare-part [false false] [left right]
  (if (= left right) :undetermined (< left right)))
(defmethod compare-part [true false] [left right]
  (compare-part left [right]))
(defmethod compare-part [false true] [left right]
  (compare-part [left] right))
(defmethod compare-part [true true] [left right]
  (if (not= (count left) (count right))
    (< (count left) (count right))
    (->> (map compare-part left right)
      (filter boolean?)
      first)))
No matter whether left and right are vectors or numbers (the only two options) it always enters the first option and often explodes because seqs can't be compared with < what did I do wrong?

Madara Uchiha16:12:16

REPL shenanigans (can't reload multimethods just by sending them to the repl 😞)

phill17:12:16

I sometimes put a (comment (def bla-bla nil)) before (defmulti bla-bla...) to make it easier to remember to clobber it before re-executing it.

pppaul22:12:36

you can remove symbols from a namespace, how to do so will be editor/repl dependant. there is probably a special form that dose so as well.

Jo20:12:35

Hey, I'm quite new to clojure and looking for a bit of help. I'm trying to filter a list of hashmaps by a search term, but I'm trying to pass in multiple keys that can be used to filter. I could use or but I want to make a reusable function that can take data search-term & keys , so if I have an example input of:

[{:country "England" :city "London"} {:country "England" :city "Frimley"} {:country "France" :city "Paris"} {:country "France" :city "Marseille"}]
I want to filter the list by country and city, so if my search-term is "Fr" it would return:
[{:country "England" :city "Frimley"} {:country "France" :city "Paris"} {:country "France" :city "Marseille"}]
Appreciate any help, I've been googling and trying to do something for a while but just been struggling with it

hiredman20:12:30

Start by breaking it down into parts

hiredman20:12:07

A function that given a map, a single key and a term returns true or false

hiredman20:12:57

A function that given a list of keys and a search term, returns a list of functions that take a map and return true or false

hiredman20:12:50

A function that takes a list of functions and a map and returns true if some of the functions return true when applied to the map

valtteri20:12:51

#C053AK3F9 would be an appropriate channel for this. Many helpful people there!

Jo20:12:50

@U0NCTKEV8 so I've gotten a function to start with that can work with 1 key:

(defn filter-by-search [items term key]
(filter #(str/includes (key %) term) items))
I just don't really understand how to change it if I turn key to & keys and do the same, it isn't really making sense @U6N4HSMFW thanks, I will try in there too

hiredman20:12:49

I strongly recommend not trying to write a single function, but decompose the problem into sub problems until you can solve them, and solve each sub problem as a function, and solve the overall problem using the functions you wrote for subproblems

Jo20:12:08

I will give that a try, thank you

Jo20:12:28

Thanks @U0NCTKEV8 I've got something that works now