This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-06
Channels
- # announcements (58)
- # babashka (43)
- # babashka-sci-dev (22)
- # beginners (8)
- # biff (8)
- # calva (62)
- # circleci (3)
- # clerk (6)
- # clj-kondo (27)
- # cljsrn (9)
- # clojure (61)
- # clojure-austin (4)
- # clojure-conj (3)
- # clojure-europe (11)
- # clojure-losangeles (2)
- # clojure-nl (2)
- # clojure-norway (4)
- # clojure-spain (5)
- # clojure-uk (2)
- # clojurescript (51)
- # data-science (1)
- # datascript (4)
- # emacs (33)
- # events (14)
- # funcool (14)
- # gratitude (13)
- # introduce-yourself (1)
- # jobs (9)
- # lsp (58)
- # malli (23)
- # missionary (30)
- # nextjournal (9)
- # off-topic (35)
- # proletarian (2)
- # re-frame (5)
- # remote-jobs (7)
- # shadow-cljs (2)
- # spacemacs (7)
- # sql (26)
- # testing (12)
- # vim (1)
- # web-security (3)
- # xtdb (2)
I'm a total ignoramus when it comes to Babashka, so this is almost definitely a really dumb question. But how do I use external deps? It looks to me like the role of Babashka in Biff is the various tasks? And that I should be able to add any deps of my choosing to deps.edn
like normal? Which I tried but I'm getting errors when trying to use the Cognitect AWS API.
yep, babashka is used for the tasks like bb dev
. for babashka deps, you can add them to tasks/deps.edn
. deps.edn
is for the main app.
The aws issue is most likely due to this: https://github.com/jacobobryant/biff/issues/134
as mentioned there, you can fix it by downgrading the Jetty adapter. if you happen to be using web sockets, you'll need to set them up differently from what's demonstrated in biff's example app.
Crap, should've checked issues! I was digging through the AWS API repo to no effect! Thanks @U7YNGKDHA 🙏:skin-tone-2:
no worries :)
I've got a bit of a knot to untangle. There's this vector [:user/email :asc]
and this set {:admin :player :editor :tester}
that need to make a round-trip through a string in the hx-vals
attributes on some buttons, out to the client for clicking, back to the server as JSON, and into a database query as a vector and a set. The contents of these collections is different for each button. Taking a cue from how biff delivers the csrf-token, I used cheshire/generate-string
on a map like this:
{:limit 5
:offset 0
:sort-order [:user/email :asc]
:filter-by :user/roles
:filter-set #{:admin :player :editor :tester}}
Which gives me something like this for the hx-vals
attribute:
"{\"limit\":5,\"offset\":0,\"sort-order\":[\"user/email\",\"asc\"],\"filter-by\":\"user/roles\",\"filter-set\":[\"tester\",\"admin\",\"editor\",\"player\"]}"
When it gets back to the server, some stuff happens, in Reitit, I believe, and eventually the :params
key of the req
map has something that looks like this for me.
{:limit "5"
:offset "0"
:sort-order ["user/email" "asc"]
:filter-by "user/roles"
:filter-set ["admin" "player" "editor" "tester"]}
So I made a little middleware function that uses malli/decode
to coerce that into my original map. I must admit, I was a little proud of this solution. And this hubris of mine clearly angered the gods. For it worked, and it worked really well. It forced me to make a nice schema for my data, which kept me from straying from the path. And with the help of the malli.transform/default-value-transformer
I could put default values in this schema and keep them all in one place instead of scattershot throughout the functions just to make sure they got what they needed.
But then tragedy struck!
If I wanted to filter on :admin
alone, I'd have a hx-vals
attribute with something like '{\"filter-set\":[\"admin\"]}'
and that will go through to the :params
key as {:filter-set "admin"}
! A lone string, instead of a vector of one string. It all comes tumbling down here, because Malli won't coerce that into a set of a single keyword.
There's a couple solutions I can think of here. For example, I've discovered that if a JSON array of a single item has a trailing comma after that item, it comes through to the :params
key as a vector of a single string I can work with. But I'm not to keen on inserting those commas or depending on them always working. Or I think I can write some custom code for malli/decode
that can be tucked into the schema and will handle this edge case. But I feel like I'm approaching this problem the wrong way. Maybe there's something I'm missing here. Is there a bit of configuration I can do that will change this behavior of turning JSON arrays of single items into lone strings? Or a cleaner way to handle this data?I have an awkward solution for the moment.
[:filter-set
{:default #{:admin :player :editor :tester}
:decode/string {:leave #(if (set? %) % (hash-set (keyword %)))}}
[:set keyword?]]
Adding that :decode/string {:leave … }
bit to the schema seems to handle the issue. But I'm not confident about it.huh, that is some interesting behavior from malli. I wonder if that's some sort of heuristic for dealing with query params (e.g. if you have a url with .../?foo=a&foo=b
then you'd want to get {:foo ["a" "b"]}
, but if you have just .../?foo=a
then you'd want {:foo "a"}
.
I would sidestep this whole issue by encoding the map to edn first and then if needed wrap that in json:
;; Option 1
[:input {:type "hidden"
:name "query-opts"
:value (pr-str {:limit 5 :offset 0 ...})}]
;; Option 2
[:button {:hx-vals (cheshire.core/generate-string
{:query-opts (pr-str {:limit 5 :offset 0 ...})})}]
;; handler is the same for either option
(defn handler [{:keys [params]}]
(let [query-opts (clojure.edn/read-string (:query-opts params))]
...
))