By Developers, For Developers

Historical errata for Web Development with Clojure, Third Edition

PDF PgPaper PgTypeDescriptionFixed onComments
9ERROR

On the Chapter 1 page 9 the mentioned command will throw the following error:

user=> (create-migration “guestbook”)
Execution error (IllegalArgumentException) at user/create-migration (user.clj:40).
find not supported on type: mount.core.DerefableState

The stacktrace:

RT.java: 866 clojure.lang.RT/find
core.clj: 1547 clojure.core/select-keys
core.clj: 1540 clojure.core/select-keys
user.clj: 40 user/create-migration
user.clj: 39 user/create-migration
REPL: 10 user/eval33684

2019-07-24This can be fixed by running (start) before attempting to create your migration (see Page 6). \nThis seems to be a common gotcha though, so we'll figure out how to prevent other readers from experiencing this as well. Any suggestions are welcome. Thanks!
viiiTYPO

wrote memorization -> rote memorization

2019-06-22
37TYPO

:require should contain [muuntaja.middleware :refer [wrap-format]]
not [muuntaja.middlware :refer [wrap-format]
(The e in middleware is missin)

(defn handler [request]
(response/ok
{:result (-> request :params :id)}))

doesn’t work for me. It works with changing :params to :body-params

2019-06-22
41ERROR

(fn [{{:keys [id]} :path-params}]
(response/ok (str "

the value is: " id "

")))}]])

should be
(fn [{{:keys [value]} :path-params}]
(response/ok (str "

the value is: " id "

")))}]])

2019-06-22
9ERROR

Sorry, please ignore above reported error =) here is corrected post:
user=> (create-migration “guestbook”)
Execution error (IllegalArgumentException) at user/create-migration (user.clj:40).
find not supported on type: mount.core.DerefableState

2019-07-24This can be fixed by running (start) before attempting to create your migration (see Page 6). \nThis seems to be a common gotcha though, so we'll figure out how to prevent other readers from experiencing this as well. Any suggestions are welcome. Thanks!
78SUGGEST

After introducing message-form and home in the “Reimplementing the Form” section, there is no render statement left for the unitiated. Had to add
(r/render
(home)
(.getElementById js/document “content”))

in order to see anything when working through the sections. It looks like later you add a dispatch and other things to take care of this, but at this step, we need something.

2019-06-22
82ERROR

After telling us to add an errors atom and using it in “send-message!” and “errors-component” it is not defined anywhere. I believe it needs to be added to “message-form” through the led statement of “errors (r/atom nil)” or “errors (r/atom {})”

2019-06-22
83SUGGEST

To add cljc support we are told to add “src/cljc” to the cljsbuild source-paths, but we also need to add it to the greater source-paths too. It could be convenient to add that as an addition in the “Share Code With the Client” section.

2019-06-22
37ERROR

In the handler function, it should be :body-params instead of :params, like so:
{:result (-> request :body-params :id)}

See Server Spec: github.com/metosin/muuntaja/blob/master/README.md

2019-06-22
37ERROR

The snippet does not work for me.

1. In the “require” there’s a typo: “[muuntaja.middlware :refer [wrap-format]]”, an “e” is missing in “middleware”
2. I had to change “{:result (-> request :params :id)}” into “{:result (-> request :body-params :id)}”
3. I’m not sure whether this is an error or not, but I don’t understand why we need to define “wrap-formats”, because it basically just wraps “wrap-format”. In my case, using “wrap-format” directly seems to work fine.

2019-06-22
38TYPO

We’re supposed to test the curl command without the “Accept” header, so the command should be:

$ curl -H “Content-Type: application/json” -X POST -d ’{id localhost:3000
{result

2019-06-22
viiiTYPO

Last sentence has an extra ‘to’ in it: “The following
chapters will teach you how to effectively to build your web applications using
this stack.” should be “…how to effectively build”

2019-06-23
19SUGGEST

The original home.html does not contain these divs:

and none of the text mentions them until this full file reveal on page 19. Seems like they should either be in the original template or the text should suggest adding them.

Also, when the list of messages HTML is added to home.html, there’s no indication of what it should replace (I naively replaced the entire file with it, and then discovered several pages later it was only supposed to replace a small part of the file.

2019-06-23
72SUGGEST

The source code examples has a lot of versions of the different stages being explained in the book. But there is nothing in the book that synchronizes between which version/directory in the examples and the stage of the book.

The only thing is sometimes the caption in the book for a code snippet has the directory of the example. Its not consistent and nothing in the body of the book says to switch. Like on page 72 it shows guestbook-reagent, but then for the next several pages (rest of the chapter?) its guestbook-reagent-start.

Related to that is if you do switch directories while following along you need to restart things including redoing the migrations.

In any case, having some guidance of how to stay in sync between the book and the examples would be helpful.

(Really enjoying the book though!)

2019-07-23Thanks for the suggestion, we really appreciate it! \nThe large number of examples are due to the fact that we clone each step from a single git repository. \nWe'll try to minimize any jumping back and forth to keep a linear progression. \nDo you think it would be helpful to also add a CHANGELOG.md or READER-NOTES.md file that briefly describes each example directory?
20ERROR

The text says the HTML should contain:

But if you do that, you end up with whitespace in the textarea and the code doesn’t trim message so that whitespace may be longer than 10 characters, so after adding schema validation, “empty” submissions may still pass and get stored in the DB.

Note that on page 25, it shows the corrected HTML:

name=“message”>{{message}}

but it’s easy to miss that change!

2019-06-23
31TYPO

Text says:

:request-method—The HTTP request method, such as :get(), :head(), :options(),
:put(), :post(), or :delete()

The () should not be present on any of those.

2019-06-23
36SUGGEST

If the app is already up and running when you do this:

We can now replace the ring.util.response reference with a reference to ring.util.httpresponse and update the handler as follows

You’ll probably get an exception that the alias response already exists in that namespace. I had my editor connected to the REPL running the app and tripped over this.

2019-07-24Good catch. thanks. \nI've added a brief explanation of 'ns-unalias' in the next beta release, but I worry it might be a bit advanced. An alternate solution would be to place the changes to 'ring-app.core' before the application restart (i.e. next to the dependency inclusion). \n What do you think?
39SUGGEST

The constant switching back and forth of the handler between returning HTML (with your IP address) and the :id value in the various examples leading up to this page is very confusing. It’s very hard to tell whether you’ve made the right edits to your core.clj file because the file is just repeated each time without any clear indication of exactly what changed. Sometimes the surrounding text calls out a change, sometimes it doesn’t. I’m finding the book’s flow pretty frustrating at this point!

2019-07-23I've updated the flow in this section, but I am willing to take a second pass. Please let me know what you think of the next release and open another erratum if you have more concerns! \n \nThanks for the feedback!
41SUGGEST

The text has us add /echo/:value but then says:

The server will now handle the POST() method for the route:

Which applies to the previous change made, and there seems to be no example to GET on the new /echo route?

2019-07-24
46SUGGEST

empty? is already a built-in filter so this example could be better.

2019-07-24
46TYPO

“The handler accepts an addition parameter that holds the content of each block” — should be “additional”

2019-06-23
47SUGGEST

This example:

(fn [args context-map content]
(.toUpperCase (get-in content [:uppercase :content])))

would be much clearer if it didn’t use content as an argument (which is confusing when it contains :content).

Perhaps block would be a better name?

(fn [args context-map block]
(.toUpperCase (get-in block [:uppercase :content])))

2019-06-23
40ERROR

To illustrate routes from which we can capture URI segments, we have
this snippet:

(def routes
[[“/” {:get response-handler
:post response-handler}]
[“/echo/:value”
{(fn [{{:keys [id]} :path-params}]
(response/ok (str "

the value is: " id "

")))}]])

The URI segment uses :value but the handler uses :id. The snippet
should be:

(def routes
[[“/” {:get response-handler
:post response-handler}]
[“/echo/:value”
{(fn [{{:keys [value]} :path-params}]
(response/ok (str "

the value is: " value "

")))}]])

Also, there’s no `curl` example demo-ing this.

Finally, for Clojure beginners like me, the destructuring of the
function arguments is really difficult to read. It took me a while to
understand that it could simply be replaced by:

(fn [request]
(response/ok
(str "

the value is: "
(get-in request [:path-params :value])
"

")))

To be honest this section is a bit messy: we talk at the same time
about routes that handle POST, and routes with a :value URI
segment. There should be two different paragraphs in my opinion.

2019-07-23Thanks for the feedback! You're right, that section was a bit confusing. \nI've made the function destructuring match the path, I've added a curl example, and I've taken a second pass at the section as a whole. \n \nWith regards to removing the destructuring, we feel that it is an essential part of reading and writing idiomatic clojure, and I'd rather elaborate on it and/or reference the relevant section of the clojure primer appendix than discourage its use. If the appendix isn't clear enough, or a repeated reference to it would be useful, please let us know! \n \nI hope the next release addresses your concerns, but please open another erratum if it doesn't. \n \nThanks!
46TYPO

“The handler accepts an addition parameter” should be “The handler accepts an additional parameter”

2019-06-23
57SUGGEST

The whole “Application Core” paragraph is not very clear. We just have big snippets of code without without much explanations. I had to experiment with the “mount” library by myself to understand what was going on.

Suggestions:

- explain what a “resource” is (it’s written several times in the first paragraph, but it’s a pretty generic term)

- add explanations about the “mount” library, what problems it addresses and how it works (I didn’t find it very intuitive, as a beginner)
- say a word about this weird syntax (I’m a clojure beginner and didn’t undersand it: “(mount/defstate ^{:on-reload :noop} …”

Maybe a dedicated section about “mount” in the previous chapter would be nice, since this is where other imporant libraries are inroduced.

2019-07-24
71SUGGEST

The introduction of ClojureScript doesn’t say what version of which project to start with. It refers to the guestbook app that we worked on earlier, but that has all sorts of code added that bear no relation to the code shown in the ClojureScript section’s examples — for example, the long list of dependencies we’ve added to project.clj and all the HTML we added to the home.html page.

Should we create a fresh guestbook project and start over? Should we continue on from some previous stage of the guestbook app?

I think we should start over with a fresh guestbook-reagent project but I’d have to guess at the correct options to create whatever template we need here.

2019-07-24
72SUGGEST

The text says:

“Next, let’s update our project.clj to add the plugin and provide a default configuration for it.”

and then shows a partial project.clj. It does not mention that the first line shown is updated/needs to be updated, otherwise, your code will not run:

:resource-paths [“resources” “target/cljsbuild”]

The text needs to make this clear.

2019-07-24
76ERROR

The text says:

“The > indicates that the p tag is nested inside the div tag.”

But it’s an h1 tag, not a p tag.

2019-07-23
80SUGGEST

At this point, it matters a lot what state your server-side code is in! Looking at the example code in the previous ten pages, I figured that creating a new guestbook-reagent project as a starting point for ClojureScript was the right thing to do, because that’s the name shown in the code listings — and now I have none of the server-side stuff that it seems to be assuming.

Now I have to go back to the beginning of the chapter, switch over to the previous (heavily modified) guestbook app and reapply all the ClojureScript changes from scratch.

This is extremely frustrating — the flow of the book makes it very unclear what code each section should be starting with and exactly what changes should be applied (since they are not all called out in the text and nor all they highlighted as comments in the code fragments).

2019-07-24Sorry about that. We've added an explicit statement that we're modifying our original guestbook application to the beginning of the Add ClojureScript Support section. Hope that helps!
82SUGGEST

string/join is introduced without any require to provide the alias. Presumably [clojure.string :as string] should be added to the :require clause in the ns?

2019-07-24
83SUGGEST

And there’s the [clojure.string :as string] instruction, buried in a paragraph of text, on the next page after the code. For folks who get to the end of a code listing, save, and go off to refresh their browser to try stuff out, it’s going to be frustrating not to have known about that change earlier (see the erratum I submitted for page 82 about exactly this).

2019-07-24
84ERROR

send-message! sprouts a third argument called messages at the end of page 84, without mention in the text, and without any corresponding changes to how it is called.

2019-07-24
88SUGGEST

It seems that any existing messages in the DB at this point are going to appear differently to any new ones added through the UI:

[TaggedValue: LocalDateTime, 2019-06-23T15:18:14.435]
Longer message!

- Sean

6/23/2019, 3:37:46 PM
This is a Reagent message!

- Sean

Is that “expected” behavior at this point? Have I missed something in my code edits? Should the chapter include code to format those Java Time objects (on the server, I assume)?

2019-07-24I am unable to reproduce this with the current version of the book's code, but I don't have a good explanation as to why you're encountering this. I suspect that the luminus version you're using has something to do with it, but I'm not sure at this time. If I've attempted to recreate this error improperly it should be caught in the final tech review, but I'll keep an eye out for java-time related issues as we continue work on the beta. Thanks!
93ERROR

The text talks about removing messages as an argument from message-form and its call to send-message! — it doesn’t mention removing messages from the call to message-form at the end of the home function — and page 93 still shows that argument being passed.

2019-07-24
108ERROR

The pages up this point have shown how to test POST /api/message but I decided to also test GET /api/messages.

At first, I thought I was getting the messages back, as expected, but instead of a 200 OK status, I get a 500 error status and then I noticed there’s a spec failure:

{
“spec”: “(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:spec$23245/messages]), :type :map, :leaf? false})”,
“problems”: [],
“type”: “reitit.coercion/response-coercion”,
“coercion”: “spec”,
“value”: {
“messages”: [ …

Hard to tell what is failing from that but I suspect the timestamps are ending up as Java Time values due to the read column protocol extension that seems part of the original Luminus template, and these fail the inst? check.

Also, the spec for POST /api/message has status 200 and 500, but it returns 400 for the errors cases and only a generic error for the 500 case.

2019-07-24As with the other java-time issue, I am unable to reproduce it. I suspect that the luminus version is to blame. It is also possible that you've misconfigured muuntaja. I'll keep an eye out for issues like this one, and I'll try to reproduce it once more in the final review. Sorry I can't give a more satisfactory response.
108ERROR

Re: local date/time and inst — I confirmed this by editing guestbook.db.core and commenting out the extension of jdbc/IResultSetReadColumn so DB timestamps are NOT converted to Java Time. This passes the inst? check and you get 200 OK back.

2019-07-24It's possible that this issue due to incorrect configuration of transit handlers, possibly due to the version of luminus you're using. I am unable to reproduce the errors you're getting related to java-time.
91ERROR

References to code snippets in the re-frame section refer to “:messages/loading” not “:messages/loading?” as they should.

2019-07-23
131TYPO

Its not shown that the `(ns guestbook.handler…` section should go into `guestbook-websockets/src/clj/guestbook/handler.clj`

2019-07-24
144TYPO

In the line:
This means we can keep using :messages/set as our event, instead of adding an intermediate event to process our response.

Should that be :messages/load instead of :messages/set?

2019-07-23:messages/load is responsible for fetching the data with the :http effect, and then it dispatches the :messages/set event with the processed response. \n \nWe're able to still use :messages/set because we are specifying the path to the data we want. If this wasn't the case, we'd need a different event, because :messages/set expects a list of messages, but the unprocessed response is a map that looks like this: \n`{:messages [{:user "foo" :message "bar"...} ...] ...}`
145SUGGEST

Its not clear from the text or in the code snippet that you need to edit (defn message-form in addition to creating the text-input function

2019-07-24
109SUGGEST

using cljsbuild is confusing, the nesting of options in the project.clj is daunting. Shadow CLJS simplifies this process alot and suggest using that to show clojurescript instead.

2019-07-23We actually were planning on switching from cljsbuild+figwheel to shadow-cljs for a while. We just got around to it this release! Great minds think alike :P
78SUGGEST

instead of printing the contents of atom to the page why not put as console log ?

(.log js.console (:name @fields)) . put this at the bottom of the message form, its how i would debug

2019-07-24In this case, we add it to the page because it is live. We can see changes to our field as we type. If we were to do this in the console, it would get noisy pretty quickly. This is also the first example of a value rendering from a r/atom, so it is valuable in that regard as well.
48TYPO

[muuntaja.middlware :refer [wrap-format]])) ->

[muuntaja.middleware :refer [wrap-format]]))

2019-07-23
132SUGGEST

I believe the “(rf/dispatch [:form/clear-fields response])” should be put in the `“:message/send!” instead of “handle-response!” so it only clears the submitting form, and not the second mid submitting form.

2019-07-31We clear the fields when we receive a response so that we can confirm that there were no errors with the message. If we clear on send, we may delete partially completed messages that are rejected by the server. The ideal behaviour would be to disable the inputs while we send, but that will be added later.
23ERROR

In the section on Validating Input, the path name has changed to “guestbook-validation/src/clj/…” - which is not correct.

2019-10-21This is a compromise we made to effectively work with multiple versions of the same project. If this is confusing to many readers, we will add a note to explain this.
72TYPO

Escaped quotation mark:
The last sentence in 4. “Introducing Clojurescript, JavaScript Interop” the quoted word “black” is displayed as “&lquot;black&rquot”

2019-10-21
51ERROR

" As we saw, Luminus places HTML templates in the resources/templates folder."
The correct folder is “resources/html”.

2019-10-21
86TYPO

Typo on the last sentence of that page “taht” should be “that”.

“… validate-message function to ensure taht the message …”

2019-10-21
22TYPO

There is a sentence:
“The guestbook page should now look like the following figure:”

The figure following this sentence shows the page as it was before the styling changes. Not as it looks after styling is applied.

2019-10-22
80TYPO

Extra closing parenthesis on following function:

(defn home []
[:div.content>div.columns.is-centered>div.column.is-two-thirds
[:div.columns>div.column
[message-form]]])))

2019-10-21
87SUGGEST

[cljs.pprint :refer [pprint]] suddenly appears in the require list of the source code. Maybe left in by accident?

Maybe I missed this one being added, but I can’t spot it being required/used earlier.

2019-10-22
112SUGGEST

It wasn’t immediately obvious to me what line should be added to project.clj for cljs-devtools. It wasn’t hard to look up, and I found it on clojars.

On a related note, for me a mention of the best way to find the the project dependency strings to put in project.clj might have been useful info when I started reading the book.

(p.s. very much enjoying the book, and looking forward to the remaining chapters!)

2019-10-22Hi Mark, \n \nLooks like we missed the dependency in the text, so that's been fixed in the new beta. The bigger picture is that there are a couple of ways to package libraries nowadays. Traditional approach is that the author of the library packages it in a jar and publishes it to a Maven repo such as Clojars. However, Cognitect has now released tools.deps tool chain that allows using git repos as dependencies instead. So, the best option for figuring out how to add a particular dependency is by following the instructions on the project page. In practice, majority of libraries are still packed as jars, but the nuance is a bit out of the scope for the book. We might look into adding an appendix on the topic if the time allows.
127ERROR

inst? predicate doesn’t return true for a LocalDateTime object.

2019-10-22Hey Mark, good catch! We modified our jdbc/IResultSetReadColumn protocol to convert timestamps to java.util.Dates (which do satisfy inst?) in the reagent section, but we forgot to discuss it in the book. I have updated Chapter 4 to explain this.
35ERROR

response/ok isn’t part of ring.util.response on ring 1.7.1

2019-10-21
17TYPO

Book says

“You’ll also note that the templates are set up to use Twitter Bootstrap as the default scaffolding for the page layout”

I think the template uses Bulma, not bootstrap?

2019-10-21
24SUGGEST

I’m a bit confused about the source of the layout/render function. It looks like the request argument is never used (it’s even greyed out in Cursive). Why is this argument included if it isn’t used?

2019-10-21Pages commonly need information from the request (e.g. the user in the session), so the general purpose render function in Luminus takes it as an argument so that it can be passed to Selmer if and when necessary. However, since none of the HTML templates included in Luminus actually use the request, it is not passed to Selmer, and so it is greyed out by IntelliJ.
37TYPO

(ns-unalias ns response) should be (ns-unalias ns ’response)

2019-10-21
24SUGGEST

It would be slightly more readable if the sentence “Let’s select the name, message, and errors keys from the flash session and merge them with our parameter map.” were before the code snippet containing the merge function.

Another suggestion: is it possible for you to enable a plugin like Rainbow Brackets (available in e.g. VSC, IntelliJ, and as RainbowParenthesis in vim) when generating the code listings?
Although probably disliked by some, on paper we do not have the assistence of an editor to easily show which parentheses match when using just black on white.

2019-10-29I've moved the sentence, thanks for the suggestion! \n \nAs far as rainbow parentheses, there isn't a way for us to that currently. I would guess that the issue with print that you brought up is one of the reasons. \n \nIn case you aren't aware, the source code in the book is available as a .tgz or .zip archive [here](https://pragprog.com/titles/dswdcloj3/source_code) and that can be opened in your editor of choice.
5TYPO

Instead of “guestbook-base” you probably meant just “guestbook”. The save for pages 5,16,17.

2019-12-12The use of "guestbook-base" is intentional. Throughout the book, we discuss snapshots of the same app through the different stages of development. Due to the way that code is shared with the readers, we have to have different directory names for each version. We'll add a brief section to the preface before we publish to explain things like this. \n \nThanks for the notes!
42TYPO

Something is probably missing in the following sentense “Since we have Finally, we’ll add a route called /multiply.”

2019-11-27
43TYPO

Should be “generate” instead of “generated” in “This function is initialized using a map that specifies the handler
functions that will generated the responses for 404, 405, and 406 client errors.”

2019-11-27
80SUGGEST

It may seem obvious, however while following the guestbook-reagent-start/src/cljs/guestbook/core.cljs example I defined (r/render …) function and then the following (defn message-form..) and (defn home []..). After that, I updated the (r/render [home]…) however I forgot to put it after the (defn home []..) function which leads to the following error in the browser console (and empty browser page content)
Error: Assert failed: Invalid Hiccup form: [nil]
I tried to google for it, but haven’t found any hints.
After moving (r/render [home]) to the end of the file, the issue was solved.
Probably you can add a hint to not to forget that (r/render) should be at the end of the file or mention the error and why it could be caused.

2019-12-16
82ERROR

Was it intended to have different styles for the button:
[:input.btn.btn-primary …] on page 82
and
[:input.button.is-primary…] on page 79?
Anyway [:input.btn.btn-primary …] doesn’t provide the expected button style.

2019-12-16
196ERROR

’‘’print i’’’ is not perfectly valid Python code anymore. It was in Python2 (whose support ends this year), but in Python3 one should use ’‘’print(i)’’’

Moreover, the code snippet is not very idiomatic Python code, IMO. Pythonistas learn to use list comprehension:
’’’
for i in [val*val for val in range(1,6)]:
if not i%2:
print(i)
’’’

2020-01-25Hi, thanks for the heads up regarding the use of print, I'll update the example. While list comprehension would be more idiomatic, a for loop is easier to follow for people who are not familiar with python and illustrates the differences between imperative and functional approaches more clearly.
112TYPO

On the image of page 112, the content type is set to “application/edn”; however when the button “Try it out” is pressed the response body is “Malformed ”application/edn" request.". Is there any missing setting?

2020-01-25Hi Oleh, I've double-checked and it works correctly for me. The error you're getting is probably due to a mistake you've made in the "Value" textarea in Swagger UI. Try the example value: '{:name "Jane" :message "Hello There!"}' and see if that works for you. \n \nAlso, please note that the 'Example Value' displayed by Swagger UI does not support EDN, and will produce the error you're seeing. You have to either write your own EDN, or select "application/json" to use JSON.
145TYPO

This line:

Next, we need pass our timeout and our callback function from :message/send! :

Is missing “to”, and should be:

Next, we need to pass our timeout and our callback function from :message/send! :

2020-01-25
7235TYPO

I’m sorry, I don’t know the PDF page number because I’m using the mobi version in the Kindle desktop app on my Mac. It only shows locations, which in this case is 7235 of 9069, which probably isn’t helpful to you.

The location of this issue is in Chapter 6 “Planning Our Application” near the end of the section “Adding User Management” when we add the /api/session endpoint to fetch the session. As another point of reference, this issue is on line 73 of guestbook-session/src/cljs/guestbook/core.cljs.

The “:session/set” event registration code in core.cljs is shown as:

(rf/reg-event-db
:session/set
(fn ​ [db [_ {:keys [identity]}]]
​ (assoc db ​ :auth/user identity ​ :session/loading? false)))

But the :identity map is wrapped inside a :session map within the response, so the destructuring needs to reflect that by going one level deeper.

(rf/reg-event-db
:session/set
(fn ​ [db [_ {{:keys [identity]} :session]]
​ (assoc db ​ :auth/user identity ​ :session/loading? false)))

2020-03-23The unwrapping of the top level response map is actually provided by the :success-path option passed to :ajax/get from :session/load. When we define :session/load, we provide :success-path [:session] to the :ajax/get effect. This will unwrap the HTTP response and pass the session itself to the success event, :session/set. \n \nWhen we define the :ajax/get effect on PDF page 150 (it's under "Events and Effects in Re-Frame > Effect Handlers"), we allow an optional ":success-path" to unwrap the response body. This allows us to keep knowledge of our HTTP responses' top-level structure inside our load-type events. This keeps our set-type events focused on how the data itself relates to our re-frame DB, and allows us to use them regardless of where the data comes from. There's a brief explanation of :success-path as it pertains to :messages/load and :messages/set just after we introduce the :ajax/get effect. \n \nHope that helps! Please reach out if you have any further questions. Thanks for reading!
249245ERROR

In Appendix 5 the items resource fires the :malformed? decision key also for GET requests. This makes impossible to read items form the file (the resource always returns “item value cannot be empty” for GET requests). Modifying the associated function to fire only for POST requests solves the problem for me.

:malformed? (fn [context]
(if (= :post (-> context :request :request-method))
(-> context :request :params :item empty?)))

218218ERROR

I followed the shadow-cljs introduction in Chapter 5 “ClojureScript Development Tools” and then want to let the example run with ‘npx shadow-cljs watch app’ I received the error message
‘Can’t find ’shadow.cljs.devtools.cli’ as .class or .clj for lein run: please check the spelling.
Syntax error (FileNotFoundException) compiling at (/private/var/folders/93/t1ql7sl95r178ljln7lc4mdc0000gn/T/form-init11009519573600646549.clj:1:126).
Could not locate shadow/cljs/devtools/cli__init.class, shadow/cljs/devtools/cli.clj or shadow/cljs/devtools/cli.cljc on classpath.’

After some googling and a diff to the example project I could exclude typos in my project copy but see that in the ‘project.clj’ of the example code the additional dependencies
‘[com.google.javascript/closure-compiler-unshaded “v20190618” :scope “provided”]
[org.clojure/google-closure-library “0.0-20190213-2033d5d9” :scope “provided”]
[thheller/shadow-cljs “2.8.39” :scope “provided”]’

are missing in my version. After putting them there a second error message comes up, which then be solved by swapping the dependency of clojurescript from “1.10.238” to “1.10.520” like in the example project.

While this finally fixed all errors I want to notify you. I am clearly just beginning with clojure/script and am not sure if this is a typical beginner problem, but I get stucked in the workflow of always extending the previous made version of the guestbook app by writing down the constructions in the book. If the error can be fixed by adding the missing dependencies in the ‘project.clj’ maybe its worth to add this in the description about the changes in the ‘project.clj’ on page 218.

Love the work you are doing with the book!

56SUGGEST

Code should not be wrapping e.g. ​``“CURRENT_TIMESTAMP” was rendered as ​“CURRENT_TIME-STAMP” leading to confusion

173ERROR

Missing services route code for /api/logout

100TYPO

“You saw how to use Leiningen create and manage applications”.
Missing a “to” after Leiningen.

221TYPO

In the text you have “Let’s place the query in the resources/find_user.sql file in our project.” (find_user.sql) however, the right file name is “users.sql”. The correct name is mentioned in the code block, however, following just text instructions can lead to errors.

224TYPO

The text “Let’s add a new file called resources/find_user.sql and place the following query there:” is a duplication of the same statement that was already mentioned on the page 221

228ERROR

It seems that something is missing in this section.
Executing (jdbc/insert-multi! …) gave me “Unable to resolve symbol: jdbc…” error and after I added this dependency to the project I got the following error:
Execution error (IllegalArgumentException) at clojure.java.jdbc/get-connection (jdbc.clj:437).
db-spec HikariDataSource (HikariPool-1) is missing a required parameter
I ended up adding records via extending queries.sql file

Thanks for the cool stuff!

Categories: