Fork me on GitHub

hi, i'm working on a simple website using Luminus and reframe. i'm having trouble figuring out how to retrieve entries inside a database from my backend and display them as a list on the frontend. in the luminus tutorial i read, it's done by passing the results of a database call to a selmer/render-file call, which in turn allows the template file specified in the render-file call to access those results. however, i'm not sure how to utilize this if i am using reframe to generate the frontend (which works by adding a script file generated by cljs to the template file) or if i'm supposed to use other means of retrieving those results. any help would be appreciated; thanks in advance


This is really a general question about web develop, nothing specific to clojure


When using re-frame (or, for example, react if you were writing in Javascript), you'll want to have an endpoint in your server that re-frame calls


And that endpoint would return the data read from the server, in json format (or edn, etc)


Another approach would be to have the backend expose the data as an API and a separate reagent/re-frame app for the front end.


this is tangential to my question above, but i'm also rethinking about using Luminus to build a web application. i've come across this site: which recommends using Compojure to create a web application, and i assume there are other viable options out there. how do you recommend i choose the proper means of creating a web application? i'm also curious about any general thoughts here.


@ashbadine91 If you are just getting started with Clojure, I strongly recommend building a small server-side web app using just Ring and Compojure to gain an understanding of how Clojure deals with the web's HTTP request/response idiom. From there you can go on to build a simple REST-like API that allows a client (such as curl at the command line) to make requests and get data back as JSON. Then you can start in on the ClojureScript side of things and build a small client web app that makes those REST requests and deals with the JSON it gets back. Luminus bundles together a lot of moving parts and if you don't understand how the basics work, you'll flounder when trying to adapt a basic Luminus project to your needs. I do not recommend Luminus for beginners.


thanks a lot for the project suggestions sean. it's good to get a sense of direction since i've felt fairly lost on how to get a website working using clojure


Yeah, it can be a bit overwhelming because Clojure favors composing small libraries over the structured frameworks that many other languages have. It makes it much harder for beginners to get up and running in Clojure as far as web apps are concerned, but once you get used to it, assembling just what you need for any given solution is pretty straightforward.


Are there any books/resources you would recommend for learning Clojure+ClojureScript as a supplement to actually using the languages? I only read, which I thought would be enough but now I'm having second thoughts.


I don't know much about ClojureScript resources, but I generally recommend Getting Clojure and Clojure Applied as two solid books for the Clojure side of things. There's a long list here but my personal advice is to stick to books from Pragmatic primarily, with maybe some from O'Reilly and/or Manning, and avoid Packt.


i'll take a look at those, thanks


If you want to look at a small, database-backed, server-side web app that uses several libraries but is aimed at beginners: -- the README links to a variant built with Integrant and Reitit (instead of Component and Compojure).


That variant, in turn, links to a version with a SPA front end, using Inertia.js and some middleware (I have no experience with that). At some point, I will get back to cljs and build a version of that usermanager example that has a re-frame front end and an API built into the backend. Some day...

John Bradens07:02:22

Ok so I'm trying to use prismatic/dommy just to learn how to use clojure libraries. I am following the learn-clojurescript book. One example has

(gdom/setProperties password #js {"type" "password"})
How would I write this using dommy? I required dommy.core :as dommy. I tried
(dommy/set-style! password :type :password)
I can't get the formatting write for this and idk where to find an example.

John Bradens07:02:00

I have

(let [password (dommy/create-element :input)
Can I make it a "password type" here? I want it to show up as black dots when typed 😕 And also just learn how to translate between doing the same things in different libraries & how to figure out the correct formatting

John Bradens07:02:52

Ok I figured out I do

(dommy/set-attr! password :type "password")
and it worked!


Can someone explain this to me

(ns toy-project1.subs
   [re-frame.core :as re-frame]
   [clj-time.coerce :as timec]))

 (fn [db] (timec/from-long (get-in [:current :dt] db))))
Error :
[:app] Configuring build.
[:app] Compiling ...
[:app] Build failure:
The required namespace "clj-time.coerce" is not available, it was required by "toy_project1/subs.cljs".
"clj_time/coerce.clj" was found on the classpath. Maybe this library only supports CLJ?

Rupert (All Street)13:02:41

Have you added clj-time to you lein project.clj or deps.edn?




     [reagent "1.1.0"]
     [re-frame "1.2.0"]
     [cljs-ajax "0.8.4"]
     [ "0.2.4"]
     [clj-time  "0.15.2"]

 :dev-http {8280 "resources/public"}

 {:app {:target :browser
        :output-dir "resources/public/js/compiled"
        :asset-path "js/compiled"
         {:app {:init-fn toy-project1.core/init}}


this is my shadow-cljs.edn

Sampo Toiva13:02:34

@U0EGWJE3E clj-time is a wrapper for Joda Time and is meant for Clojure side of things. You'd want to take a look at cljs-time.

Sampo Toiva13:02:35

Moreover, clj-time is deprecated. See here:


Oke, I changed it to this :

[com.andrewmcveigh/cljs-time "0.5.2"]


and the code to this

(ns toy-project1.subs
   [re-frame.core :as re-frame]
   [cljs-time.coerce :as timec]))

 (fn [db] (timec/from-long (get-in [:current :dt] db))))


but still this error :

:app] Compiling ...
[:app] Build failure:
The required namespace "cljs-time.coerce" is not available, it was required by "toy_project1/subs.cljs".

Sampo Toiva14:02:38

Have you restarted your repl? And actually, things have changed a bit since I last looked at this. Cljs-time is a bit old library in itself, so something else might be better. Something like or direct usage of Google Closure library might work better.


I did not restarted it , trying it now


have to re-think some things right now


I do not see the time

Sampo Toiva14:02:23

@U0EGWJE3E what do you mean with you do not see the time? The code above isn't showing the time. It registers a subscriber for extracting data from the app database that your views can then use.


I mean this


i have this subscription :

(ns toy-project1.subs
   [re-frame.core :as re-frame]
   [cljs-time.coerce :as timec]))

 (fn [db] (timec/from-long (get-in [:current :dt] db))))


and this in my template

(ns toy-project1.views
   [re-frame.core :as re-frame]
   [toy-project1.subs :as subs]
   [ :as events]

(defn main-panel []
   (let[text (re-frame/subscribe [::subs/time])]
         [:button {:on-click #(re-frame/dispatch[::events/fetch-weather])} "Get weather data "]]
   [:div text]]))
and I see the button but not the time


there I see this : #object[reagent.ratom.Reaction {:val nil}]

Sampo Toiva14:02:55

You need to deref the subscription with @(re-frame/subscribe [::subs/time])


and not the time

Sampo Toiva14:02:25

That will get you the value stored in the ratom. However, in your case that data is nil. There is no time.


hmm, again back to the drawing table


I know that this is the returned json which is converted to a vector

  "lat": 33.44,
  "lon": -94.04,
  "timezone": "America/Chicago",
  "timezone_offset": -21600,
  "current": {
    "dt": 1618317040,
    "sunrise": 1618282134,

Sampo Toiva14:02:58

So, somewhere, you need to initialize that data into the database. Moreover, you might wanna take a look at re-frame documentation. The layer 2 subscribers should be just that, a data subscribers. The data parsing should happen in a computation function. I.e. something like this:

 (fn [db _] (get-in [:current :dt] db))
 (fn [dt _ _] (timec/from-long dt)))


and it looks im doing the same as you but then in one step


(fn [db] (timec/from-long (get-in [:current :dt] db))))

Sampo Toiva14:02:08

Your data seems fine. In any case, check how and when you write the data into the database and remember to deref with @ .

Sampo Toiva14:02:10

Yes. The two steps are an optimization. The layer 2 query fns are rerun every time the data in app db changes. Because of this, we want them to be trivial. Just read and return data.


Thanks, I will do some debugging to see what is wrong


Right now I do not have a clue


(get-in [:current :dt] db) seems not quite right


@U0178V2SLAY what do you then think it should be ?


(get-in db [:current :dt])


hmm, then still no date to see


what does your ::events/fetch-weather event handler look like?


or rather how is the data written to the app-db when you receive it as json?


 (fn [db [_ key-path]]
   (assoc-in db key-path {})))

 (fn [db [_ key-path result]]
   (assoc-in db key-path result)))

 (fn [_ _]
    {:method :get
     :uri    ""
     :params {:lat   (:lat config/home)
              :lon   (:lon config/home)
              :units "imperial"
              :appid config/open-weather-api-key}
     :response-format (ajax/json-response-format {:keywords? true})
     :on-success      [::http-success [:weather]]
     :on-failure      [::http-fail [:weather]]}}))


perhaps the path you use with get-in should be [:weather :current :dt] ?


Then I see this error :

Uncaught Error: Objects are not valid as a React child (found: object with keys {date}). If you meant to render a collection of children, use an array instead.


I think you're getting closer


it do not feel like that


i see this on my javascript console


I’m afk for a moment, I’ll give you a few tips later


and do not hurry. this is a learning exercise


So I think your subscription is working now, or at least it's returning some kind of a datetime object. However, reagent doesn't know how to represent it in html. That's why you get a "Objects are not valid as a react child" error when you try to use it as [:div text].


So the next step is to turn that datetime object into something suitable, e.g. a string containging the date and time in some nice format


yes, I read and it seems that text is a object and not a primitive


so im now trying to see if I can see how the object looks like


so I can make a string or whatever of it


cljs-time has a function called to-string, which offers one such way to represent the datetime as a string


so perhaps try what (fn [db] (timec/to-string (timec/from-long (get-in db [:current :dt]))))) does and if it helps


oke, so I can do [:div (cljs-time text) ]])) ?


[:div (timec/to-string text)] would work also I guess, as long as you remember to require it as [cljs-time.coerce :as timec]


hmm, I tried but no output and no error message 😞


or do I have to restart the server ?


normally modifying the cljs code doesn't require restarting the server


I thought also


I had to do (fn [db] (timec/to-string (timec/from-long (get-in db [:weather :current :dt])))))


but got as answer : 1970-01-20T00:38:26.266Z which I think makes no sense


well, at least we got something working 🙂


the docs of the api says this : current.dt Current time, Unix, UTC


so that is looking well


typically the epoch (starting time) of various time systems is midnight 1.1.1970


I know but the docs stated current time and for me it is the time right now


when you work with timestamps and see a value that's close to 1.1.1970 but perhaps a few days later -> somewhere there's a mixup between "seconds after 1.1.1970" and "milliseconds after 1.1.1970"


from-long says ""Returns a DateTime instance in the UTC time zone corresponding to the given number of milliseconds after the Unix epoch.""


and I wonder if I use the right conversion from a date object to a javascript object


but the value from your API looks like it's seconds after the epoc, not milliseconds


oke, so we have to multiply with 1000 ?


so, what we need to do is convert that to ms -> (fn [db] (timec/to-string (timec/from-long (* 1000 (get-in db [:weather :current :dt]))))))


yeah, correct


that looks better




the only thing is that it is 17:44


so the summer/winter is bugging us now


and then I only want the time


wait I did not use my real location


nope, still the same problem


or schould I also use this one : `

"timezone_offset": -21600,


working with time zones is a constant pain. I'm not very familiar with cljs-time so I don't know what kind of tools it provides. One possible hack to solve your problem: that API response you get contains a "timezone_offset": -21600, -field. I guess that's the offset in seconds between the UTC timestamp and the local date. Perhaps you could add that offset to the original timestamp (before you multiply it by a 1000).


thanks, I take a break right now nothing is chancing

(fn [db] (timec/to-string (timec/from-long (- (get-in db [:weather :timezone-offset]) (* 1000 (get-in db [:weather :current :dt]))))))


Thanks for all the help


Hi, is there a way to use async/chan to implement a publish/subscriber model with multiple subscribers of a single event?

Alex Miller (Clojure team)15:02:06

have you looked at pub and sub ?


awesome! thanks @alexmiller

Alex Miller (Clojure team)15:02:17

(also, feel free to ask questions in #core-async in the future)

👍 1
erre lin16:02:44

Hello, I'm not sure if this should be an SQL channel question since it is more relevant to the database connection: Basically, I'm using HugSQL, next.jdbc to interact with PostgreSQL, sth like this:

;; database 
(def db
  ;; dbtype and dbname are preferred to be drop-in
  ;; replacement for subprotocol and subname
  {:dbtype   "postgresql",
   :dbname   "name",
   :user     "user",
   :password "passwd"})

(def ds (jdbc/get-datasource db))

;; connection and CRUD
(hugsql/def-db-fns "path/to/orders.sql"
  {:adapter (next-adapter/hugsql-adapter-next-jdbc)})
Then I can run a fn, say, (add-an-order db {:order_num "xxxx", :order_note "yyyy"}) to insert a record into the database. My question is, when I run such fns (generated by HugSQL), they will try to connect to the database I defined. Is this a only-once connection that will be closed after the sql statement is done? Or every time a long-time connection will be created, stay there even after the fn finishes, and take some RAM until I find I'm running out ram? I think the connection is of the first type: short-time and closed once data gets inserted. Where could I find more info on this? Thank you for your help


I'd suggest asking in #hugsql -- I'm not sure how it manages connections. The recommended best practice is to set up a connection pool (which next.jdbc supports directly, using HikariCP or c3p0) and then pass that around so that operations that do getConnection() and then close() are using a pool of cached connections instead of standing up a new connection to the DB every time.


It's normal to set up a connection pool at the start of your program and leave it in place until your program shuts down @U02UW9X8DUG

erre lin05:02:22

Thank you @U04V70XH6. Really helpful advice. I'll try out the tips you mentioned.

erre lin13:02:20

Hi@U04V70XH6, I have a quick question regarding hikari-cp (a Clojure wrapper to HikariCP) and next.jdbc. I read next.jdbc 's doc and find it uses HikariCP directly without the wrapper. When I tried to use the wrapper, it creates a datasource using its own db-spec hash map, where next.jdbc's :dbtype is declared as :adapter . Other differences include :user (next.jdbc) vs :username (hiker-cp) and :dbname vs :database-name Passing a connection pool created by hikari-cp to next.jdbc/get-connection will throw me an error: Unknown dbtype:, and :classname not provided. I guess there is some collision. Since next.jdbc works with HikariCP well, I'll just drop the wrapper lib. But I'm curious if my guess is right. Wondering if you happen to know anything about this?


A map function makes a call to an external api with account ids. When I print the the structure [accountid, apiresult] it's printed separately, asynch. ie [account1 ""] [account2 ""] and then "apiresult1" "apiresult2" How can I group the output together?


mapping is lazy and that's usually not what you want when interacting with and API or other side effects like printing what happens is that the data isn't calculated until the data structure is inspected by the repl print operation, so you get a weird interleaving of printing of debug info from your code and printing of data structure contents by the repl if your main goal is to see the account and result together, it's better to write your function so it joins the two into data, and then print the resulting data eg:

(defn get-api-result [input]
  {:request-data input
   :result (do-query input)})
instead of printing inside the get-api-result function, print what it returns

👍 1

Is there a better way of doing this? (filter #(clojure.string/ends-with? full-url %) ["" ""]) The idea is to allow through a full-url, only if it ends with any of a matching whitelist domain. It could return true or false. I thought about doing apply, but couldn't quite get it to work.

Darin Douglass19:02:09

you could use something like and parse the urls to make the intent more clear. otherwise, it reads find to me ¯\(ツ)


Thank you - will check that out 🙂


Ah regex 🙂 Then I would have two problems 😉


Thank you, will have a read.


(filter #(clojure.string/ends-with? "" %) ["" ""])
;;=> ("")
Or did I misunderstand?


user=> (import '( URI))
user=> (#{"" ""} (-> "" URI. .getHost))
user=> (#{"" ""} (-> "" URI. .getHost))
Could just use maybe?


All great stuff, reading.


Ah the problem with your approach @U4ZDX466T is that it'll fail with or (basically, the host part should be ignored):


(#{"" ""} (-> "" URI. .getHost))


However, this `(filter #(clojure.string/ends-with? "" %) ["" ""]) ;;=> ("")` is a valid problem with my approach too!


I mean, I don't think there's a secure solution to that requirement.


(clojure.string/ends-with? "" "")
;;=> true


Or I can't think of one, at least.


Yes, indeed. It's very tricky. I may just park it for now.


Depending on your situation, you could consider whitelisting CIDR blocks instead, or something like that.


It's for a chat forum, so any user can post any link as text...danger will robinson danger!


I'm going to go away and ponder...


@U11EL3P9U or similarly bad "<>"


you can literally put anything after # and the browser happily ignores it if there's no match on the target page


edit: URI is safe to use, URL does a network query for hash-code / equality checks

John Bradens20:02:47

Hi I'm doing the learn-clojurescript book. In one lesson we make a weather conversion widget. It says to try adding a button that will reset the input-box where you type in the tempurature to be converted. I'm trying to do something like

(defn reset-temp (gdom/setTextContent temp-input "")) 
(gevents/listen reset-button "click" reset-temp)

John Bradens20:02:06

And it's not working. Any ideas what I am doing wrong?


that’s an invalid way to specify a function. Do you see any compilation warnings?


(defn reset-temp [] (gdom/setTextContent temp-input ""))

John Bradens21:02:43

Oh I see. I have

(defn reset-temp [_] (gdom/setTextContent temp-input ""))

John Bradens21:02:48

I didn't copy it over correctly

John Bradens21:02:14

In index.html I have

        <input type="reset" id="reset-button">

John Bradens21:02:31

Then this is my whole file:

John Bradens21:02:59

(ns learn-cljs.temp-converter
   [goog.dom :as gdom]
   [ :as gevents]))

(defn f->c [deg-f]
  (/ (- deg-f 32) 1.8))

(defn c->f [deg-c]
  (+ (* deg-c 1.8) 32))

(def celsius-radio (gdom/getElement "unit-c"))
(def fahrenheit-radio (gdom/getElement "unit-f"))
(def temp-input (gdom/getElement "temp"))
(def output-target (gdom/getElement "temp-out"))
(def output-unit-target (gdom/getElement "unit-out"))
(def reset-button (gdom/getElement "reset-button"))

(defn get-input-unit []
  (if (.-checked celsius-radio)

(defn get-input-temp []
  (js/parseInt (.-value temp-input)))

(defn set-output-temp [temp]
  (gdom/setTextContent output-target
                       (.toFixed temp 2)))

;; 5 event handling callback 
(defn update-output [_]
  (if (= :celsius (get-input-unit))
    (do (set-output-temp (c->f (get-input-temp)))
        (gdom/setTextContent output-unit-target "F"))
    (do (set-output-temp (f->c (get-input-temp)))
        (gdom/setTextContent output-unit-target "C"))))

(defn reset-temp [_]
   (gdom/setTextContent temp-input ""))

;; 6 attach event handlers 
(gevents/listen temp-input "keyup" update-output)
(gevents/listen celsius-radio "click" update-output)
(gevents/listen fahrenheit-radio "click" update-output)
(gevents/listen reset-button "click" reset-temp)

Filip Strajnar20:02:49

I wish to encrypt files with AES (256 bit key, CBC mode) using streams (more specifically file streams), and i don't wish to reinvent the wheel so i'm wondering if there is an existing library that'd allow me to do that?


I’d like to perform the job of a reduce which produces a sequence. In this case where each element in the resulting sequence depends in some arbitrary way on the previous element in the resulting sequence and an element in the reduced over collection. I can do this with reduce, no problem, but I would like to do this lazily, i.e. so that the calculation for a specific element in the resulting collection is only performed on request. Any thoughts on how to accomplish that? This is still kind of on the boiler in my head so I might be foobaring something in my thinking…


A common idiom that I use is:

(map (fn [prev current] (f prev current))
   (rest xs))


one note is that it will only call the mapping function for every element that has a previous. If you want to call it for every value, you can do something like:


(map (fn [prev current] (prn prev current))
     (concat (rest xs) [nil]))


hmm…this was to replace something like:

  (fn [[a p] v] [(conj a (operation p v)) v])
  [[] nil]
i.e. a reduce which reduces over a collection, but also depends on the previous value of the resulting collection (`a` above)


hmm…seems I can probably do this somehow via reductions…ok think I have enough to keep digging. Thanks for the pointers!

👍 1

> i.e. so that the calculation for a specific element in the resulting collection is only performed on request as a side note, if you want to avoid doing any unnecessary work reduction, then lazy sequences can sometimes get you into trouble due to chunking. If doing a little extra work isn't an issue, then the lazy sequence versions should work fine. If it is an issue, you may want to explicitly apply the reducing function yourself on request.


(reduce (fn [acc [prev current]]
          (conj acc (operation prev current)))
        (partition 2 1 coll))
or what you had already with the composit accumulator destructure


(defn foo
  [op init coll]
  (if (< (count coll) 2)
      (let [x (apply op (take 2 coll))
            acc (conj init x)]
        (cons acc
              (foo op acc (rest coll))))))
lazy-seq version, but I think you only want the last value so reduce is better


and I guess reductions is still better if you need the transitory values in between - lazy-seq requires too much sequence walking boilerplate so it's much less clear

Ben Sless07:02:43

There's also a reductions transducer in the xforms library, then you wont have to worry about chunking


thank you all for the input. Specifically for this particular case I was looking to calculate various trend metrics for finance. Exponential moving average is an example, i.e. you get a coll/seq in, you produce a new coll/seq as output based on a calculation which depends on current element and last calculated value. For ema specifically it seems reductions is beautiful:

(defn ema [^long n coll]
  (let [a (/ 2 (inc n))]
      (fn [pv v] (+ (* a v) (* (- 1 a) pv)))
      (first coll)
      (rest coll))))

(ema 6 (range 5))
=> (0 2/7 38/49 484/343 5164/2401)
I’ve run across reductions a few times and never really saw the light…clojure keeps expanding the mind.


where the first argument is the length of the coll, I do this as my actual function has a transducer arity and I think the transducer needs to be told the length of the input as it can not do “global” operations on the indata


anyway…thanks @U051SS2EU, @U7RJTCH6J and @UK0810AQ2! Will hold on to your notes as I’m sure I will have use for them over the course of this project.


@UK0810AQ2 when using lazy-seq directly I don't think chunking comes into play? it's higher level stuff like map that respects chunks I thought


yeah - no worry about chunks when using lazy-seq directly

(cmd)user=> (defn lazy-map
              [f coll]
                (when (seq coll)
                  (cons (f (first coll))
                        (lazy-map f (rest coll))))))
(ins)user=> (take 1 (lazy-map println [1 2 3]))
(cmd)user=> (take 1 (map println [1 2 3]))


perhaps some application of lazy-seq?