By Developers, For Developers

Historical errata for Web Development with Clojure

PDF PgPaper PgTypeDescriptionFixed onComments
43ERROR

It appears the namespace for guestbook.routes.auth is missing a reference. The code snippet:

(ns guestbook.routes.auth
(:require [compojure.core :refer [defroutes GET POST]]
[guestbook.views.layout :as layout]))

should be:

(ns guestbook.routes.auth
(:require [compojure.core :refer [defroutes GET POST]]
[hiccup.form :refer :all]
[guestbook.views.layout :as layout]))

Otherwise the following exceptions is thrown:

Exception in thread “main” java.lang.RuntimeException: Unable to resolve symbol: label in this context, compiling:(guestbook/routes/auth.clj:6:9)
at clojure.lang.Compiler.analyze(Compiler.java:6380)
at clojure.lang.Compiler.analyze(Compiler.java:6322)

2013-09-05
46ERROR

Should the code snippet not include home-routes?

(handler/site
(routes auth-routes
app-routes))
(session/wrap-noir-session
{:store (memory-store session/mem)})))

2013-09-05absolutely right :)
46ERROR

On page 45 the routes refer to id:

(defroutes auth-routes
(GET “/register” [id] (register id)) (POST “/register” [id pass pass1]
(if (= pass pass1) (redirect “/”) (register id))))

And then on page 46 they refer to handle:

(defroutes auth-routes
(GET “/register” [handle] (register handle)) (POST “/register” [handle pass pass1]
(if (= pass pass1) (redirect “/”) (register handle)))

2013-09-05
45SUGGEST

With additions to the :require statement it would be clearer to include the namespace in the code example. While sometimes it is mentioned in the body of the text, having it embedded in the code example would be more full proof.

2013-09-05
47ERROR

Missing closing parentheses for this statement:

(defroutes auth-routes
(GET “/register” [handle] (register handle)) (POST “/register” [handle pass pass1]
(if (= pass pass1) (redirect “/”) (register handle)))
(GET “/login” [] (login-page)) (POST “/login” [handle pass]
(session/put! :user handle) (redirect “/”))
(GET “/logout” [] (layout/common
(form-to [:post “/logout”] (submit-button “logout”)))
(POST “/logout” [] (session/clear!)
(redirect “/”)

Corrected:

(defroutes auth-routes
(GET “/register” [handle] (register handle))
(POST “/register” [handle pass pass1]
(if (= pass pass1)
(register “/”)
(register handle)))

(GET “/login” [] (login-page))
(POST “/login” [handle pass]
(session/put! :user handle)
(redirect “/”))

(GET “/logout” []
(layout/common
(form-to [:post “/logout”]
(submit-button “logout”))))
(POST “/logout” []
(session/clear!)
(redirect “/”)))

2013-09-05
34ERROR

(if (not (.exists (java.io.File. “db.sq3”)))
doesn’t work for me on OS X, this does:
(if (not (.exists (java.io.File. “./db.sq3”)))

Great read so far, very helpful, thanks! Matthias

2013-09-05
5TYPO

Windows/Linus

->

Windows/Linux

2013-09-05
13TYPO

This namespace contains the the entry
->
This namespace contains the entry

2013-09-05
ViiTYPO

“Functional languages are ideal for writing large application because..”

This should probably be “…applications…” or "…a large application….

Rgds

Mark

2013-09-05
viiiSUGGEST

“In most languages data can either passed around by value or by reference.”

might be better as:

“In most languages data can either be passed around by value or by reference.”

or

“In most languages data can be either passed around by value or by reference.”

2013-09-05
viiiTYPO

“so any substantial amount data is passed around by reference”

should perhaps be:

“so any substantial amount of data is passed around by reference”

if I understand authors meaning correctly.

2013-09-05
7TYPO

This is done by navingating to the
->
This is done by navigating to the

2013-09-05
48ERROR

The login page presented on page 48 is different to the login page on 46 (excluding additions):

Page 46.

(defn login-page [] (layout/common
(form-to [:post “/login”]
(text-field {:placeholder “user id”} “handle”) (password-field {:placeholder “password”} “pass”) (submit-button “login”))))

Page 48.

(defn login-page [error] (layout/common
(form-to [:post “/login”]
(text-field {:placeholder “scren name”} “id”) (password-field {:placeholder “password”} “pass”) (submit-button “login”)
(if error [:div.error “Login error: ” error]))))

2013-09-05
49ERROR

Incorrect signature:

(defn handle-login [id pass pass1]

should be:

(defn handle-login [id pass]

2013-09-05
49ERROR

The wrap-noir-validation is not prefixed with the namespace ‘vali’.

(def app (-> (handler/site
(routes auth-routes
app-routes))
(session/wrap-noir-session
{:store (memory-store session/mem)})
(wrap-noir-validation)))

2013-09-05
50ERROR

The login page never uses the helper ‘control’:

As seen on page 48:

defn login-page [error] (layout/common
(form-to [:post “/login”]
(text-field {:placeholder “scren name”} “id”) (password-field {:placeholder “password”} “pass”) (submit-button “login”)
(if error [:div.error “Login error: ” error]))))

(defn control [id field]
(list (vali/on-error id error-item) field [:br]))

2013-09-05
50ERROR

The update control helper is missing the field id:

(defn control [id field]
(list (vali/on-error id error-item) field [:br]))

should be:

(defn control [id field]
(list (vali/on-error id error-item) (field id)[:br]))

2013-09-05
50ERROR

The change in signature of the control helper breaks the registration page:

(defn control [id field]
(list (vali/on-error id error-item) field [:br]))

The original control helper is:

(defn control [field name text]
(list (label name text)
(field name)
(vali/on-error name error-item)
[:br]))

2013-09-05
49ERROR

Some of the validation error errors are incorrect:

(vali/rule (not= id “foo”)
(vali/rule (not= pass “bar”)

should be:

(vali/rule (= id “foo”)
(vali/rule (= pass “bar”)

2013-09-05
18SUGGEST

If the reload was successful, you should be able to run (create-guestbook-table) in the Instarepl to create the table.
(use ’guestbook.models.db)
(create-guestbook-table)

-> You should specify to turn off the live mode of the Instarepl, otherwise (create-guestbook-table) will return an exception saying that that the table exists already.

2013-09-05
31TYPO

they are also available to handlers definied inside it.
->
they are also available to handlers defined inside it.

2013-09-05
69TYPO

Deliting Records

should be:

Deleting Records

2013-09-06
37TYPO

Unlike Hiccup and Envlive,
->
Unlike Hiccup and Enlive,

2013-09-05
43ERROR

(ns guestbook.routes.auth
(:require [compojure.core :refer [defroutes GET POST]]
[guestbook.views.layout :as layout]))

-> You need also to require hiccup forms:

(ns guestbook.routes.auth
(:require [compojure.core :refer [defroutes GET POST]]
[hiccup.form :refer :all]
[guestbook.views.layout :as layout]))

2013-09-05
27TYPO

At the bottom of the page it says:
:remote-addr - the IP client of the address or the last proxy from whichthe request originates

It should say: :remote-addr - the IP address of the client …

2013-09-05
46SUGGEST

(defroutes auth-routes
(GET “/register” [handle] (register handle))
(POST “/register” [handle pass pass1]
(if (= pass pass1)
(redirect “/”)
(register handle)))

In the previous sections of the book ‘handle’ was written ‘id’. It may confuse the reader.

2013-09-05
46ERROR

(:require … [noir.session :as session])
shall also be added to the ‘auth’ namespace.

2013-09-05
47TYPO

(POST “/logout” []
(session/clear!)
(redirect “/”)

Two closing parentheses are missing at the end.

2013-09-05
48TYPO

(text-field {:placeholder “scren name”} “id”)

->

(text-field {:placeholder “user id”} “id”)

2013-09-05
49ERROR

(wrap-noir-validation)))
->
(vali/wrap-noir-validation)))

2013-09-05
53TYPO

to ensure the separation of concerns between the service and the client.
->
to ensure the separation of concerns between the server and the client.

2013-09-06
54SUGGEST

At this point, we should be able to start up the REPL by running the start-server in the liberator-service.repl namespace.

This suggestion seems confusing to me. Please give the command to start the server and explain why it is interesting to proceed like this.

$ lein repl
user=> (use ’liberator-service.repl)
user=> (start-server)

2013-09-26This was meant for starting the REPL in the IDE so that you can develop interactively against it as shown in chapter 1.
55SUGGEST

(ANY “/” request

Maybe you should explain what ‘request’ mean.

2013-09-06
10TYPO

Application is called `guestbook` not `guest-book` so `(use ’guest-book.routes.home)` doesn’t work, it should be `(use ’guestbook.routes.home)`

2013-09-26Where does the `guest-book` reference appear, I don't notice it grepping through the text.
43SUGGEST

For newcomers to Clojure, instead of saying: “new namespace”. Please use terms they understand. Just say we’ll create a new file.

Instead of saying: “We’ll add
the page to a new namespace called guestbook.routes.auth. The namespace will
need to reference other namespaces similarly to the home namespace.” you could say:

We’ll add
the page to a new file named auth.clj under the routes folder, this file will contain the namespace called guestbook.routes.auth. This namespace, like the home namespace, will
need to reference similar namespaces.

(or something to that effect)

2013-09-14I've expanded the explanation on how namespaces relate to files and how they're organized. I do feel that it is worth using the language terminology however.
44SUGGEST

It is very confusing from the context as to where the auth-routes is being added? In the “auth” namespace or in the handler.clj ??

“”“In order to make our new page available to the client, we’ll also have to define
a new route for it. We’ll wrap it in a route definition called auth-routes.”“”

2013-09-26I actually reworked section heavily and created a fully working code sample to go along with it. The next revision should be much easier to follow.
44TYPO

The site is running on port 3000 as per previous instructions but second to last para of page 44 tells the reader:

then navigate to http COLON SLASH SLASH localhost:8080/reg-ister to confirm that the page loads correctly

2013-09-05
44ERROR

You really need to indicate as to which piece of code the changes are being made.

Require noire.session… but where? Please make it clear.

2013-09-05I had a lot of comments on this section, so I reworked it quite a bit. There's now a working code sample to go along with it as well.
5TYPO

Towards the bottom, the text: “Ctrl-T on Windows/Linus” should instead read: “Ctrl-T on Windows/Linux”. You’re referring to the OS and not the creator of said OS. :)

2013-09-05
ixTYPO

we’ll become familiar the web stack ->
we’ll become familiar with the web stack

2013-09-05
175TYPO

First line of para says: “While the book focuses on using Eclipse for development,…”

It should say “… Light Table for development,…” as that is the IDE used all through the book if I’m not mistaken?

2013-09-06
71SUGGEST

It is not clear what this line means, how is the user supposed to do what is being asked of them? :

Let’s start the REPL by running (start-server) in the reporting-example.repl names-pace.

2013-09-26I'm not sure what the best way to address this would be. The first chapter shows how to use the integrated REPL in Light Table and run functions in it. This is referring to the same thing.
69TYPO

Deliting => Deleting

2013-09-07
13ERROR

The application structure outline shows db.sq3, which isn’t placed there by leiningen. Probably later in the book it’s added.

2013-09-09
19ERROR

Following along in the book, I had to reconnect (a second time) in order to run (save-message) to the db from the instaREPL.

Before reconnecting, it complained that save-message was already bound to guestbook.routes.home/save-message.

2013-09-09
72TYPO

Here is example,, Book says on p72, “Let’s run read-employees to make sure everything is working as expected”

You don’t tell me how to run this. Sorry chap 1 does not cover this. There is also no mentioning of running the create-employee-table. You want to run read-employee before explaining that create-employee-table should be run first?

Where should I run it? In the Instarepl? In light-table? if in light-table, how? I press CTRL-ENTER on function. Nothing happens.

Thank you.

2013-09-26It should be the same process as the one followed when creating tables in the guestbook project in chapter 1. \n \nYou would connect LT to the project by hitting Ctrl+Enter in the reporting-example.repl namespace. Once connected then you can open the instaREPL and run (use 'reporting-example.models.db) which will load that namespace in the REPL. These are the same steps as with the guestbook. \n \nI could clarify further that the namespace has to be loaded in the instaREPL before it can be referenced.
19TYPO

Now, that we wrote functions to add and remove messages
-> Now, that we wrote functions to add and read messages

2013-09-09
16TYPO

The save-messagefunction
> The save-message function

2013-09-11what page does this show up on, I don't notice it in the latest draft (might be fixed :)
23TYPO

The application has three main parts
-> The application has four main parts

1. There is the guestbook.handler namespace
2. Next we have the guestbook.routes.home namespace.
3. The layout of your application is managed by the guestbook.views.layout namespace.
4. Finally, we have the guestbook.models.db namespace.

2013-09-09
51ERROR

The additional feature to check credentials should be added to the handle-login function created on page 48, not inline in the POST “/login” function.

2013-09-09
51ERROR

The function is defined as create-user, but the handle-registration function calls create-user.

2013-09-09
51ERROR

(defn handle-registration [id pass pass1]
(if if (= pass pass1)
(do
(db/create-user {:id id :pass (crypt/encrypt pass)) (redirect “/”))
(register id)))

should be:

(defn handle-registration [id pass pass1]
(if (= pass pass1)
(do
(db/add-user-record {:id id :pass (crypt/encrypt pass)})
(redirect “/”))
(register id)))

2013-09-09
73ERROR

(defemployee-template
(template [$name $occupation $place $country]))

Text needs to indicate where this is supposed to go. One can assume it is in the reports.clj file but it is not obvious from the context.

2013-09-10
74,76SUGGEST

The screenshots on pg 74 and pg 76 refer to localhost:8080/table and localhost:8080/table respectively even though it is not introduced until later on pg 78 after the routes for these have been defined.

Perhaps it will suffice to tell the users to look for the pdf output file in the project root directory?

2013-09-10
32TYPO

This route extracts the name and message form parameters
-> This route extracts the name and message from parameters

2013-09-12
9TYPO

The first sentence on the page is “In most languages data can either passed around by …”
It seems to me the word ‘be’ is missing from that sentence.

2013-09-12
195TYPO

" quote splicing" should be " unquote splicing"

2013-09-13
viSUGGEST

You’ve written a fine book on the title topic. Don’t try to teach the language too. That’s a stride too wide, and you’ll fall in the river.

Include and act on something like the following preface paragraph …

“This book teaches you to develop web applications in the Clojure programming language. If you don’t already know Clojure, you have to be prepared to learn it as you go along. To help you do the latter, the text is sprinkled with references to a companion book, the outstanding ‘Programming Clojure’ by Halloway and Bedra (there are alternatives, of course). If you’re already a Lisp programmer, you can get by on the official language documentation at www.clojure.org, which we also key the text to. ”

Even if you don’t publish the book this way, this exercise should help sort out which bits of the language are needed when.

Keep up the good work!

2013-09-26
19ERROR

Last paragraph: save-message function has not been defined yet at this point (it is defined on the next page), therefore using the guestbook.models.db namespace does not produce a reference error as indicated in the text.

2013-09-17
35TYPO

Small typo: “…and handler client requests” rather than “…and handle client requests”.

2013-09-18
102ERROR

The code to handle the actual file upload is broken in a couple of ways. Firstly, noir.io/upload-file takes two arguments, rather than the one being passed - I found that the following works:

(noir.io/upload-file (str File/seperator “img” File/separator) file)

And secondly, the image tag is referring to /img/{user_id}/{file}, whereas it gets uploaded to the root of the img directory. I’ve not got fair enough through to find out if the user directory gets created later in the chapter, but at least to start with the image tag is broken after upload.

2013-09-18
xSUGGEST

s/better to have a general formula that you can derive others from than having/better to have a general formula from which you can derive others than to have/

2013-09-20
152TYPO

anHTML -> an HTML

2013-09-20
xSUGGEST

Suggestion: “To make an analogy with mathematics, having a general formula that you can derive others from is better than having to memorize a whole bunch of formulas for specific problems.” Keeps parallel clauses (for ease of understanding: the original uses two different forms of “have”) and aids understanding by putting the “is better than” together between the things compared.

2013-09-20Thanks, that's definitely better wording. :)
188TYPO

The last line on the page reads “If each step was even a little more comlex then we’d be really lost. On top of”. Presumably “comlex” should be “complex”.

2013-09-21
197TYPO

In the last paragraph of section 9.15 “however” is misspelled as “howver”: “Howver, there are many other uses for protocols and I encourage you to take the time to discover these on your own.”

2013-09-21
181SUGGEST

It appears that the Emacs Starter Kit is no longer available, at least through Phil Hagelberg, who says, “Version 3 of the Emacs Starter Kit is implemented as a prose guide to various packages and settings which can greatly improve the Emacs experience.” Though the old packages are probably still available on Marmalade, you might consider substituting Bozhidar Batsov’s Emacs Prelude (github.com/bbatsov/prelude), which seeks to do something similar.

2013-09-22
26ERROR

The code box headed guestbook-snippet/home.clj does not include the submit button shown in the screen shot (figure 9, page numbered 13 of the PDF, which is the 27th page in the PDF).

2013-09-23
30SUGGEST

Regarding: “Try adding a comment in the guestbook to see that it’s being printed in the console”

At this point, still running in LightTable, it’s not obvious how to see this println output. View > Console doesn’t show the output.

2013-09-26
31TYPO

first paragraph of 1.2 Your first paragraph “Since have it open”

2013-09-23
198TYPO

(printed page 186)

The sentence: “The body con-
sists of two print statements and and a call to sum a and b then multiply the
result by 2.” has two “and”’s.

2013-09-23
15SUGGEST

Pages 15-17, most of the code listing headings say “guestbook-snippets/home.clj”, and some say “guestbook/src/guestbook/routes/home.clj”. I think the latter would be better.

2013-09-23The ones in snippets reference the intermediate examples, where the latter references the finished version.
146133TYPO

Library name “Kerodin” should be “Kerodon”

2013-09-24
ALLSUGGEST

I’m sorry, this is not a nice thing to write, but I don’t mean any disrespect to the author. Any such implication should be attributed to my inability to express myself. I write this in frustration because this book has basically made me NOT want to work with Clojure anymore.

This is a general suggestion to the author. While a web programming book is sorely needed for clojure, if its not well received by the web development community, clojure will get a black eye in the process.

You have done an admirable job, but I think you are trying to please too many quarters and have spread yourself too thin. I think a major rewrite of this book is in order. This book, in its current form is pretty much un-usable by anyone coming from Django or RoR with some basic knowledge of Clojure. That seems to be the claim made by this book strengthened by the constant hand holding that this book tries (TRIES <—) to do, yet does come up short. Providing a reference chapter at the end doesn’t solve the problem. The issue is not learning clojure, the issue is learning the specifics of the ecosystem that have become second nature for YOU the seasoned clojure person, while are opaque to anyone coming from the outside. You do not write for experts, remember this.

First of all, the book uses an experimental editing environment while the author, by his own admission, does not use light table for day to day development. This is dangerous because it can be very hard for the author to actually check all the examples for being functional and it shows. Many, if not all examples contain frustrating typos mixed with long rambling explanations which make less and less sense as one plods through the book. I have basically given up on even CONSIDERING Clojure as a web development platform because I simply don’t have the time to learn Clojure to the point where I could point out all the inaccuracies and errors in this text. By that point, this book would have become useless to me anyway.

This reinforces my original point, this book CAN NOT, by definition, cater to the Clojure expert, simply because they can simply use the libraries as they are experts. It does not serve the novice because it has too many inconsistencies which are mere annoyances for experts but horrible roadblocks for begginners! WE NEED THE EXAMPLES TO WORK. WE NEED THE TEXT TO MAKE SENSE. WE DONT WANT TO GOOGLE BECAUSE THAT"S WHY WE PAID FOR A BOOK! This is also an indictment of the cynical editing process (or lack thereof) of the publishers of this book.

Here are my suggestions:

1. Get rid of Light Table references! they are confusing and annoying and do not help in the end.
2. Introduce a simple workflow in the first chapter on how to use command line based setup (Lein to evaluate the server pieces after the user has made changes in the editor of their choice.) Use or even publish a base ubuntu image that anyone including windows people can use.
3. Need to separate the concerns. This book is not about editors or about pdf generation or about a brand of database. Its about web development in Clojure. Boil it down to its essence and build it up from simplicity without complecting factors.
4. Novices don’t care and aren’t savvy enough to setup postgres. Postgresql is NOTORIOUSLY difficult to setup. There is NOTHING about Clojure database access via JDBC that necessitates the use of Postgres. Use SQLite or even H2 or some other simple to setup DB. The point is to teach DB access not DB access to an enterprise class RDBMS in an introductory text. It detracts from the purpose and discourages.
5. the book needs to focus on web development. There is NO REASON for there to be a whole chapter on PDF manipulation! It makes NO sense. Gut it! take it out
6. The explanations need to concentrate on what’s happening and it is OK to repeat things that novices might find confusing. Remember, Web development is not done by advanced Clojure programmers, this is too trivial for people like Yourself, David Nolan and Fogus et. al. This is for mere mortals like us, and things you take for granted are SHOW STOPPERS for us.

7. The writing style: It is long and rambling (it is trying to be helpful) but it bascially makes me lose concentration because on the one hand it explains some things in excruciating detail but on the other it glosses over very specific parts which should be explained (again and again if needed). The result is a narrative that flits around without getting to the point and explaining the essence of what’s going on.

8. Why is it important to spend first half of the “photo gallery” chapter on how to setup login/user auth systems for the application? Really? Is that what’s important? In a photo Gallery? I might need that user auth but if I’m pissed off trying to get that thing to work I might abandon the whole thing in the process!

In your review of instructions provided by the text, try to follow your own steps. Or someone relatively new to Clojure ecosystem try out the steps.

Regards

2013-09-26I'm sorry that you did not find the book helpful. As you realize no book will be able to please everybody and unfortunately it looks like this will be the case for you. At this point no major rewrites will be happening as the feedback from technical reviewers and the early beta readers has been overwhelmingly positive. \n \nI would like to address your points below: \n \n1. The book originally used Eclipse as the development environment and was switched to Light Table based on reader feedback. The change was seen as positive by all the readers that have been contacted. Light Table provides an easy way to start working with code and seeing what it's doing. The book clearly states that you should try a mature development environment such as Eclipse or Emacs, but frankly they have a much steeper learning curve. \n \n2. Using the command line to develop Clojure applications is not a realistic workflow for real world development. The main advantage of a language like Clojure is the strong REPL integration in the editor. The first chapter highlights this and shows examples of a typical workflow. While, I use Eclipse instead of Light Table for development, the workflow I demonstrate is the same. \n \n3. The book is targeting the audience comfortable with web development and interested in trying Clojure for their domain. The book covers a number of realistic use cases to show the reader how many tasks are accomplished. For example, PDF generation illustrates how to access the database, retrieve records and serve binary content to the client. These are all common tasks in real world applications. \n \nThe book starts out with the simplest possible application in the first chapter. The following chapters each build up on the previous material. \n \n4. Frankly, I do not see what the difficult part of setting up Postgres is. The chapter guides the reader through the few simple steps required. On OS X Postgres can be run simply as a [user space app](http://postgresapp.com/) and on Linux it can be easily installed from standard repositories for any major distribution. There is practically no configuration required. \n \nHowever, there is absolutely nothing Postgres specific in the chapter and it you can continue using SQLite setup in the first chapter if you so choose. Once again the goal is to show best practices, and Postgres is what is predominantly used in the Clojure community. \n \n5. As explained above the tasks completed for the PDF generation are very common for realistic web applications. In fact, report generation itself is a common task. Each chapter illustrates a small application that accomplishes a specific workflow and most readers find this approach engaging. \n \n6. Unfortunately, you do not provide any information what you've found confusing or difficult to follow and this offers me no opportunity to address that. \n \n7. I'm sorry that you do not find my writing style engaging, but there's really very little I can do about that. \n \n8. The chapter goes through each aspect of building the application. The authentication is an important part of most applications. The tasks outlined in the chapter build on the ones in the previous chapters and are broken down into very small steps. On top of that there are working code samples for each section. \n \nI have been following the steps in the text and what you're seeing is the result of numerous revisions of these steps to make them as easy to follow as I can. \n \nAgain, I'm sorry this text is not helpful to you, but it sounds like you're looking for a different book from the one I wrote. \n \n \n \n
47TYPO

(if (= pass pass1)
(redirect “/”)
(register id))

I can’t find ‘register’ function. It should be ‘registration-page’?

2013-10-01absolutely
195TYPO

(let [f File. “.”)]
(println (.getAbsolutePath f)))

Missing opening parenthesis in var binding.

2013-10-07
196ERROR

(str File/separator “foo” File/separator "bar)

Missing closing quote after “bar”

2013-10-07
59SUGGEST

After removing the layout require, you also need to change this function:
(defn home []
(layout/common [:h1 “Hello World!”]))

Otherwise when you try to load the page you get an error with the missing layout.

2013-11-01What section is this in, I don't see this on page 59 of the latest beta.
113TYPO

Duplicate block of code on this page:

(defn images-by-user [userid] (with-db
sql/with-query-results
res [“select * from images where userid = ?” userid] (doall res)))

2013-10-11
89TYPO

creating a record in the daabase. —> creating a record in the database.

2013-10-15
103TYPO

No close string quote in code example at top of page.

2013-10-19
128TYPO

Screen.css:
#usermenu {

display: inline-block;;
}

2013-10-20
143TYPO

“common confuguration to all applications”

2013-10-30
10TYPO

You accidentally a few words:

Ring and Compojure libraries.1,2 the base HTTP library,

It seems that you were referencing Ring at the beginning of the sentence.

2013-10-31
11TYPO

You accidentally a word:

There are many frameworks, such Ruby on Rails, Django,
and Spring.

It should be ‘…such /as/ Ruby on Rails…’

2013-10-31
34SUGGEST

“Compojure lets you destruct a subset…”
Well, “destructure” might be better, since “destruct” sounds more like an odd past tense of “destroy”.

2013-11-01
43TYPO

Grammar: You’ve seen saw some of the commonly used functions

2013-11-01
39TYPO

“Unlike Hiccup and Enlive, Stencil, and Selmer are based on the existing…”

Delete the comma after “Stencil”, yielding either “Stencil and Selmer” or, because Selmer has not yet been mentioned, “Stencil and another, Selmer, are based…”

2013-11-01
53TYPO

(rule validator [:filed-name “error message”])

should be:

(rule validator [:field-name “error message”])

2013-11-02
44TYPO

First sentence: “Lastly, we have our route definitions, where the of what Ring and Compojure provide routes are defined”

2013-11-07
64-70SUGGEST

For section 3.3, even though the code isn’t difficult to guess, it might be nice to define the routes further up in the example so that we can compile and run the server to view (and debug) our progress as we go.

2014-02-26
64,67TYPO

The headers of the html snippets read “liberator-snippets/page1.html”, where the book says to name the file home.html. Should they be renamed to home.html and home1.html?

2013-11-11
33TYPO

Missing double quote mark on last line of this code block:

(defroutes user-routes
(GET “/user/:id/profile” [id] (display-profile id))
(GET “/user/:id/settings” [id] (display-settings id))
(GET "/user/:id/change-password [id] (change-password-page id))

2013-11-11
100TYPO

picture-gallery.modesl.db

should be

picture-gallery.models.db

2013-11-14
124TYPO

rein.util.response/response

should be

ring.util.response/response

2013-11-16
23SUGGEST

I think you’re missing a [:hr] between the [:p “Welcome to my guestbook”] and the [:form … ]. In the screenshot on the page (24) below , there’s an


.

2013-11-18
12-21SUGGEST

Hi Dimitri, Enjoying the book. Thanks for all the hard work!

Perhaps you’ve already fixed the following item in your current round of proofreading:

It looks like the text of namespaces that link to code need to be revised (and hence routes to the online code snippets):

For example, Ref: page #10

The namespace referenced in the explanatory text is “guestbook.home”, whereas the links highlighted in green read as: “guestbook-snippets/home.clj”

Thanks again,
Aditya

2013-11-18
8ERROR

Light table can’t make the connection: Unable to resolve var: reader/*alias-map*
using version 0.5.20

I wonder if using alpha software in your book is a good idea, perhaps you can be really specific which versions of code and LT you used.

2014-02-26Could you be more specific as to when you get the error. I'm using the same version and it's not exhibiting the problem you're seeing. While it's an alpha, I found that most people find it the easiest to get started. I do discuss alternatives in the appendix however. \n \n
49TYPO

“We’ll now update our route definitions to create the of what Ring and”

“the of what” seems to be a typo

2013-12-14
53TYPO

“(rule validator [:filed-name ”error message“])”

“filed-name” should be “field-name”

2013-12-14
133TYPO

“This is be a very sensitive subject for many people.”

Should be: “This can be a very sensitive subject for many people.”

2013-12-14
138TYPO

“Then we can start using it by requiring it in our namespace and calling the trace info, warn, debug, and fatal functions.”

Should match example: “Then we can start using it by requiring it in our namespace and calling the trace, debug, info, warn, error, and fatal functions.”

2014-01-10
29TYPO

The example response uses the key “:header”, but the next page as well as the Ring docs themselves use “:headers”.

2013-12-20
35TYPO

First bullet point.

“hanlder” should be “handler”

2014-01-10
64TYPO

The “for” loop is missing a leading {

2014-01-18
107TYPO

The save-thumbnail function definition is printed twice in the second listing on the page.

2014-01-10
108ERROR

“In our save-thumbnail function, we call resource-path to get the path of our public folder. ”

resource-path is not used in the function.

2014-01-27
102ERROR

In the first code listing, picture-gallery.util is required, but the namespace does not yet exist.

Also, noir.io function resource-path is required, but never used.

2014-01-27
8ERROR

A follow-up to #53320: I’m using the latest version of Light Table (which right now is 0.5.20), and I get the same error:

final project: ([org.clojure/clojure “1.5.1”] [compojure/compojure “1.1.6”] [hiccup/hiccup “1.0.4”] [ring-server/ring-server “0.3.0”] [org.clojure/tools.nrepl “0.2.3” :exclusions ([org.clojure/clojure])] [clojure-complete/clojure-complete “0.2.3” :exclusions ([org.clojure/clojure])] [ring-mock/ring-mock “0.1.5”] [ring/ring-devel “1.2.0”] [lein-light-nrepl/lein-light-nrepl “0.0.9”] [org.clojure/tools.reader “0.7.10”])
Error loading lighttable.nrepl.handler: java.lang.RuntimeException: Unable to resolve var: reader/*alias-map* in this context, compiling:(cljs/analyzer.clj:1219:9)
Exception in thread “main” java.lang.RuntimeException: Unable to resolve var: lighttable.nrepl.handler/lighttable-ops in this context, compiling:(/private/var/folders/q8/yf0cf5s14n71vhrrgpb_smx40000gn/T/form-init5422454641747359467.clj:1:3661)

etc.

I tried running the REPL at the command line and tried making an “Clojure (remoted nREPL)” connection to it from within Light Table, but that connection attempt continues infinitely.

I’m going to default to Emacs + clojure-mode + nREPL + nrepl.el for now, and assuming it works, perhaps that is a good addition for the appendix, since that development stack is well tested?

2014-02-26Emacs is definitely the most popular environment for Clojure. I talk about setting it up with `nrepl.el`, that's been recently renamed to `cider` in the Appendix A. \n \nIf you have the time, it would be good to submit an issue for Light Table. Their issues page can be found here: https://github.com/Kodowa/Light-Table-Playground/issues
32TYPO

The text says: “/all-items and item/:id” but the code uses /foo and /bar

2014-01-18
7TYPO

Another follow-up to #53320 since I haven’t seen it directly addressed:
I had the same error with a fresh clojure install / the latest version of light table. The error when following instructions in the book seems to be caused by changes in recent versions of the clojurescript compiler. I am not allowed to post a link to the github issue on light table here, but there is one.

It can be fixed by changing the clojurescript dependency in project.clj to an older version:
[org.clojure/clojurescript “0.0-2030”]

2014-02-26
35TYPO

bottom of the page, first component is listed as “hanlder” I think that it should be “handler”

2014-01-10
7ERROR

Unable to add repl connection and/or evaluate in instant repl because of clojurescript issues. Maddening start to my first clojure exploration.

2014-02-26
12ERROR

Via lighttable, http server is firing up on 8080 not 3000 as indicated by the text (localhost:3000).

2014-02-26
209ERROR

If I try to establish a repl connection using LT 0.6.0 I get the error message:

We couldn’t connect.

Looks like there was an issue trying to connect to the project. Here’s what we got:
final project: ([org.clojure/clojure “1.5.1”] [compojure/compojure “1.1.6”] [hiccup/hiccup “1.0.4”] [ring-server/ring-server “0.3.0”] [org.clojure/tools.nrepl “0.2.3” :exclusions ([org.clojure/clojure])] [clojure-complete/clojure-complete “0.2.3” :exclusions ([org.clojure/clojure])] [ring-mock/ring-mock “0.1.5”] [ring/ring-devel “1.2.0”] [lein-light-nrepl/lein-light-nrepl “0.0.10”] [org.clojure/tools.reader “0.7.10”])

2014-02-26Light Table REPL can get confused by the content in the target folder. When you build your application using lein ring uberwar, that can cause the issue. Running lein clean in the folder should fix the problem.
35TYPO

typo in => hanlder — This namespace is responsible for handling requests and responses.

2014-01-18
117TYPO

The definition of app is repeated twice.

2014-01-18
118SUGGEST

the function gallery-link is introduced again, first time it was on page 116.

2014-01-18
93TYPO

inside function valid?
vali/rule repeats :pass twice while it should be one :pass and one :pass1

this missing :pass1 is used further in the valid? function
(not (vali/errors? :id :pass :pass1))

also registration-page uses :pass1

[:br]
(vali/on-error :pass1 error-item)
(label “pass1” “retype password”)

2014-01-18
104TYPO

there is “a” instead of “an”. One paragraph is: “Let’s start by creating a add-gallery-path helper”
it should be “Let’s start by creating an add-gallery-path helper”

2014-01-18
131TYPO

ns picture-gallery.views.layout :require
includes hiccup.page twice.

2014-01-18
44TYPO

present in most applications are as follows:
• hanlder — This namespace is responsible for handling requests and responses.

——^ Should be ‘handler’

2014-01-18
200TYPO

In the “The :use Keyword” section in the first paragraph declaring is misspelled as “delcaring”

2014-01-18
7SUGGEST

Workaround for #58780, #58805, #53320

Type “lein clean” in the guestbook folder (containing project.clj).
This will update dependencies.

Source:
https
github.com/LightTable/LightTable/issues/1052

2014-02-26
41TYPO

“providing the submision form” — misspelling of submission

2014-02-08
33TYPO

In the middle of the page is a list: the 1st entry is “hanlder
”… I believe it should be “handler”.

2014-02-08
108ERROR

In the handle-upload function, the display of thumbnails of user images won’t work as it doesn’t allow for user names being included in generated URLs. Changing:

(​str​ ​“/img/”​ thumb-prefix (url-encode filename))

to:

(str “/img/” (session/get :user) File/separator thumb-prefix (url-encode filename))

works (though could be factored better).

2014-02-26If you're referring to the code in the Generating Thumbnails section, then it's intentional. The next section covers refactoring the code to use the user folder for file uploads and thumbnails.
9ERROR

I cannot get LightTable (0.6.4, Mountain Lion) to successfully evaluate `(use ’guestbook.repl)`.

It throws the exception:

```
java.io.FileNotFoundException: Could not locate guestbook/repl__init.class or guestbook/repl.clj on classpath:
RT.java:443 clojure.lang.RT.load
RT.java:411 clojure.lang.RT.load
core.clj:5530 clojure.core/load[fn]
core.clj:5529 clojure.core/load
RestFn.java:408 clojure.lang.RestFn.invoke
core.clj:5336 clojure.core/load-one
core.clj:5375 clojure.core/load-lib[fn]
core.clj:5374 clojure.core/load-lib
RestFn.java:142 clojure.lang.RestFn.applyTo
core.clj:619 clojure.core/apply
core.clj:5413 clojure.core/load-libs
RestFn.java:137 clojure.lang.RestFn.applyTo
core.clj:621 clojure.core/apply
core.clj:5507 clojure.core/use
RestFn.java:408 clojure.lang.RestFn.invoke
```

Is there some other LightTable setup I need to do?

2014-02-26
132SUGGEST

The discussion of why you need to implement a Renderable type to wrap the base layout isn’t sufficient - why can’t you just include the

[:script {:type “text/javascript”}
(str “var context =\\”" (:context request) “\\”;")]

as part of the original base definition, since it’s only that handler that uses it? It seems like a fair few hoops to jump through as it is. Why isn’t getting access to the context property (by adding ring.util.response to the ns declaration) and including it directly enough?

2014-02-26There are definitely simpler ways to access the context, but I felt this was a good place to illustrate how Ring responses are generated and how you can leverage Renderable to hook into the response cycle.
140ERROR

In listing picture-gallery-style-tests/resources/public/js/site.js the variable ‘color’ in the document.ready() function is declared but never used.

(Not sure about the page number as I’m reading the .mobi)

2014-02-16
44TYPO

Application Architecture > Listing of major components (§5.1): “hanlder” should be “handler”.

Thanks for your book, fine reading so far… :)

—jan

2014-02-26
228ERROR

The clojurescript gallery.cljs file contains the following code that gathers any errors reported by the backend when deleting images:

“(​let​ [error-str (​str​ ​”

    “​ (​.​toString errors) ​”

“​)]
(​if​ (​not-empty​ error-str)
(append! (by-id ​”error“​) error-str)))”

When will error-str never be empty here?

I had to guess the equivalent page number as I’m reading the ebook version.

2014-03-02That's definitely a bug, thanks for noticing it. A proper way to check would be: \n \n~~~ \n(when-let [error-str (not-empty (.toString errors))] \n (append! (by-id "error") (str "
    " error-str "
"))) \n~~~ \n \nI'll update the example code. \n
180ERROR

In chapter 6, converting the gallery.js file to clojurescript, the deleteImages function, the code expects returned parameters to be in a keywords map. But (for some reason) my current server implementation is returning them as a map of strings. Changing

[{:keys [name status]} response]

to

[{:strs [name status]} response]

resolves this from the client’s perspective, but I’ve been trying to find the right formula/location to tell the server to return the data in a keyword map without success (it worked fine before converting the javascript to clojurescript). This is after adding

:middleware [wrap-restful-format]

to the app definition in picture-gallery.handler.

Thanks for the book, by the way, I’m getting a lot from it if that wasn’t clear! The page number is a guess again; chapter 6, clojurescript section, gallery.js conversion.

2014-03-02Hi Oliver, \n \nI'm unable to reproduce the problem for the keys. The wrap-restful-format should be detecting the response format based on the Content-Type header, which should be set to application/edn. You could check in Chrome or Firefox what the request looks like and whether the correct Content-Type is being set. \n \nI'll close the errata item for now, but maybe we could move this to the discussion area to keep track of the issue.
7SUGGEST

I received an error similar to others when using Light Table 0.6.4 and adding the Clojure connection and evaluating a form. The error was about the tools.reader mismatch: “Unable to resolve var: reader/*alias-map* …”.

Upon running “lein deps :tree” I found that ring/ring-devel 1.2.0 was including a conflicting version of tools.reader - 0.7.3. I had to update the versions of the ring dependencies and plugins in my project.clj to:

ring-server 0.3.1
lein-ring 0.8.10
ring/ring-devel 1.2.1

I also added an explicit dependency on tools.reader:

[org.clojure/tools.reader “0.7.10”]

After making these changes, I can successfully connect and eval forms such as ’guestbook.routes.home/home. This info might help someone else with the same issue.

2014-02-26
12TYPO

The list of files in the project contains a typo:

test/
guestbook/
test/
hanlder.clj

should be:

test/
guestbook/
test/
handler.clj

2014-02-26
111ERROR

The code for show-galleries calls db/get-gallery-previews, but there’s no code shown for this, so the program won’t run.

2014-03-08Good catch, the code snippet should only be displaying the namespace declaration instead of the entire file.
4433TYPO

In the bullet point list “handler” is written as “hanlder”.

2014-03-06
3928TYPO

Describing keys in http request map, both these entries appear.

:query-string — The request’s query string.
:request-string — The request’s query string.

I’m guessing it should just be query-string, since I don’t see request-string ever again.

But if both are there, i.e., it’s not redundant, that should probably be noted. It’s kind of confusing.

2014-04-04
5342SUGGEST

This section is rather confusing overall because it’s not immediately clear that you’re rewriting the existing code in Hiccup. Much of it is the same.

In particular, this line:

(GET “/” [] (home))

Becomes:

(GET “/” [name message error] (home name message error))

and it’s not clear why. (In fact, when I first ran it, I got an exception saying that it couldn’t resolve “message” in this context. But I assume I did something wrong because when I reverted to just “(home)” it worked, and then when I put “”, it worked again!)

Keep in mind that, if we’re following your instructions, we’re moving from LightTable to CCW. A section on how to take the existing files and run them under CCW would be helpful.

(But I do appreciate the difficulty of working with such volatile targets, so please take this in the helpful spirit intended.)

2014-04-18To see why this change is made you have to make sure you understand how the new home function defined in the previous paragraph works. It has been updated to accept new parameters containing the name, message, and the error and display them.
103ERROR

Top of the page, looks like the save-thumbnail function is duplicated in the same code block.

2014-04-04
98ERROR

[picture-gallery.util :refer [galleries gallery-path]] is listed as required, but we don’t create the file/namespace, or use it.

2014-04-18These functions will be used at a later time and I felt that it would be simpler to simply include them up front to keep things moving along.
100ERROR

Let’s start by creating a add-gallery-path helper:

(defn gallery-path []
“galleries”)

Two items: a) doesn’t say where to put this (assumed the util.clj) but that breaks a bunch of other things; b) “add gallery path” is italicized which makes it look like that should be the actual name of the function or a file name. I believe it really goes in upload.clj

2014-04-18
111ERROR

The thumbnail-link and display-gallery helpers are displayed twice: once on page 111 and once on page 112. Since the “lets build two helpers” text is at the bottom of 111 I believe those functions can be stripped from page 111.

2014-04-04
112TYPO

handler.clj code is listed twice on the page

2014-04-04
116ERROR

Code block starting with (:require… isn’t labeled and it’s not immediately clear which file it refers to.

Also, the code block introduces a new form for defining the base layout. The previous form started with “(defn base” whereas this code starts with “(html5 base”. This was slightly confusing (coupled with the above).

2014-04-18
116ERROR

It looks like the http :// dropped from the jquery path:

(include-js “//code.jquery.com/jquery-2.0.2.min.js”)]

Also, previous comment about the (defn base vs (html5 base; (html5 base throws an error. Not a function? Switching back to (defn base works on page 116.

2014-04-18That's intentional, the URL is not required to specify a protocol and browsers like Chrome will complain when an HTTP URL is being linked from an HTTPS page. Omitting the protocol allows the browser to select the appropriate one depending on how the page is accessed. You can read more about this [here](http://stackoverflow.com/questions/4831741/can-i-change-all-my-http-links-to-just).
120TYPO

Reference to jquery in the layout.clj code example is missing the http prefix.

2014-04-04The prefix is not missing, but is rather intentionally omitted. Browsers do not require specifying the protocol and omitting it allows the browser to select the correct protocol when the page is loaded over http or https. When you load a page over https and the protocol for a hyperlink is specified as http, then newer browsers can refuse to load it.
7SUGGEST

I had the same error as described in #76447. I used the newest version of LightTable (0.6.5) and of the compojure-app template.

To fix it, I added the following explicit dependency to my project.clj: [org.clojure/tools.reader “0.8.4”]

Also, I executed `$ lein clean` in the command-line to clean any previously downloaded jars.

2014-04-26It would probably be a good idea to make this a topic in the forums as a few people seem to have run into issues using Light Table.
4ERROR

I got an error when I did the following:
> lein ring server
‘ring’ is not a task. See ‘lein help’.

Did you mean this?
run
> lein help
Leiningen is a tool for working with Clojure projects.

Several tasks are available:
check Check syntax and warn on reflection.
classpath Write the classpath of the current project to output-file.
clean Remove all files from paths in project’s clean-targets.
compile Compile Clojure source into .class files.
deploy Deploy jar and pom to remote repository.
deps Show details about dependencies.
do Higher-order task to perform other tasks in succession.
help Display a list of tasks or help for a given task or subtask.
install Install current project to the local repository.
jar Package up all the project’s files into a jar file.
javac Compile Java source files.
new Generate scaffolding for a new project based on a template.
plugin DEPRECATED. Please use the :user profile instead.
pom Write a pom.xml file to disk for Maven interoperability.
repl Start a repl session either with the current project or standalone.
retest Run only the test namespaces which failed last time around.
run Run the project’s -main function.
search Search remote maven repositories for matching jars.
show-profiles List all available profiles or display one if given an argument.
test Run the project’s tests.
trampoline Run a task without nesting the project’s JVM inside Leiningen’s.
uberjar Package up the project files and all dependencies into a jar file.
update-in Perform arbitrary transformations on your project map.
upgrade Upgrade Leiningen to specified version or latest stable.
version Print version for Leiningen and the current JVM.
with-profile Apply the given task with the profile(s) specified.

Run `lein help $TASK` for details.

Global Options:
-o Run a task offline.
-U Run a task after forcing update of snapshots.
-h, —help Print this help.
-v, —version Print Leiningen

2014-05-19You either did not create the application using a web template such as `lein new compojure-app myapp` or you're not running lein from the root directory of the project.
7ERROR

I either had an error or nothing happened when I tried create a connection to project.clj the way it is explained in the book.

I found a workaround : open project.clj or even repl.clj (ns guestbook.repl) and evaluate the last line with the command cmd-Enter (on OS X) or Ctrl-Enter (On Windows or Linux). Light Table will try to connect to the project and it worked for me.

117ERROR

The line “$(element).parent().parent().remove();” should read “$(element).parent().remove();”, otherwise all images are removed from the page when the delete function is executed.

193ERROR

“Clojure provides a special form called defn”
defn is not special form but macro.

2014-10-17In Clojure 1.6 it's neither, defn is simply defined using def now.
198190ERROR

In “Structuring the Code”, example Python code makes no sense.

2014-10-17
41TYPO

“For example, if we had routes /all-items and item/:id,”
should be
“For example, if we had routes /foo and /bar/:id,”

using items would be better, but you forgot to change the example code.

33TYPO

hanlder

38SUGGEST

you have to
(use ’hiccup.element)
for “link-to” to work, better saying it.

192ERROR

In the example above the heading “Namespaces” the name of the function is missing:

(defn [{:keys [id pass pass1] :as user}]
…)

I guess it should instead be something like that:

(defn login [{:keys [id pass pass1] :as user}]
…)

2014-10-17
197ERROR

The Python code is wrong:
(1) The ‘for’ lines and the ‘if’ need to end with colons
(2) The line “i = i*i” doesn’t have any effect on l, because it’s merely reassigning what the variable i refers to.
(3) The modulo operator in Python is ‘%’, not ‘mod’.
(4) The ‘print’ should be inside the ‘if’ and should be printing i, not l
Correct code would be:

l = [1, 2, 3, 4, 5]
for i in range(5):
l[i] = l[i]*l[i]
for i in range(5):
if i % 2 == 0:
print i

However, this is very unidiomatic Python. It would be done more like:
l = [1, 2, 3, 4, 5]
m = [i for i in l if i*i % 2 == 0]
for i in m:
print i

Granted, this requires more knowledge of Python to understand what’s going on.

2014-10-17Fixed up the Python to compile, and while I realize that you could write Python in a functional style here I wanted to illustrate that the imperative style would be valid code.
193TYPO

First paragraph in “Calling methods”:
“we pass the object its first parameter” should say
“we pass the object as its first parameter”

2014-10-17
9TYPO

“With the live mode disabled we can run commands using Alt-Enter.”

Should be “CTRL/CMD-Enter”

2014-10-17
9ERROR

“This is what gets rendered in the browser when we navigate to http localhost 3000.”

But the server is not listening on port 3000; the default port for the lein-generated project is 8080.

(sorry I had to edit the hyperlink due to incontinent censoring by the form)

14TYPO

Adding the new POST-handling route to “defroutes home-routes” in guestbook.routes.home and then evaluating the defroutes form is not sufficient for the route to be known. Actually, even stopping and starting the server via the instarepl isn’t even sufficient: One has to evaluate “guestbook.handler/app”! Took me a bit to find that out ;-)

Additionally, better tell the reader where the LightTable console actually can be found.

15SUGGEST

“Adding the Data Model”: Not sure whether needed but on should say to 1) save all files and 2) add forward declarations for functions “home” and “save-message” to “home.clj” - or else move “defroutes home-routes” to the end of “home.clj” - before disconnecting and reconnecting. Otherwise compilation errors may occur.

32TYPO

In (POST “/” [name message] (save-message name message)) the “name” is boldfaced as if it were a clojure function.

51ERROR

“The salt constitutes a randomly generated string that is concatenated with the hashed password.”

should be

“The salt constitutes a randomly generated string that is concatenated with the password before hashing occurs.”

See en.wikipedia.org / wiki/Salt_%28cryptography%29

2014-10-17
26SUGGEST

“A servlet receives requests and generates corresponding responses based on the HTTP protocol specification.”

More explicit:

"Servlets can be used to handle arbitrary network request/response exchanges. In particular, HTTP servlets are meant to handle HTTP exchanges as described in the RFCs relevant to HTTP (http www.w3.org/Protocols/). The servlet container calls instances of a servlet class with data corresponding to a request, and the servlet returns data which is used by the servlet container to build the response.

32SUGGEST

We read:

“This route extracts the :name and :message keys from the request params, then binds them to variables of the same name.”

This is actually very unusual for anyone not used to Clojure and needs to be emphasized (even in Chapter 1). I originally thought this would be an assignment by position.

Of course now you have the problem that the string designating the parameter of the handler and the string designating the parameter in the HTML form actually need to be synchronized.

46SUGGEST

“We’ll now update our route definitions to create the GET and POST /login routes for our application. We’ll also have to reference the noir.session for our routes to work”

It is not entirely clear where this noir.session lives and when it goes in and out of existence. To follow servlet semantics, it must have been dynamically bound (be thread-local) before the first ring handler to process the present http servlet request has been called (if the http request does not yet have a session, does noir create the noir.session?) This should be clarified.

48SUGGEST

This is confusing:

“Keep in mind that the session namespace must be accessed within the context of a request, meaning that it should not be used outside the scope of a route declaration.”

“within the context of a request” is clear but what is “the scope of a route declaration”?

53ERROR

(GET “/get-message” []
(noir.response/json {:message “everything went better than expected!”))

You are missing a closing } for the map.

Cheers!

2014-10-17
56ERROR

Following in nREPL, we are to create a liberator-service project, while ebook code examples throughout Chapter 3 show liberator-snippets/… path in headings, but NS refers to liberator-service. I presume it’s a “technical typo” and a matter of re-labeling all in-book source code examples’ paths. However, in a source code archive provided with the book, I also see a folder liberator-snippets, which doesn’t look like a Lein project. I don’t see explanation for this.

46TYPO

The call to (wrap-base-url) has vanished from the (def app …) created automatically by Leiningen. I was a bit confused by this because there was no reference to its removal in the text, but when it re-appeared on page 49 I realised it is probably a typo.

52TYPO

The handler/init function doesn’t have the create-user-table function added, so if you blow away the db this app will now fail to work properly.

98ERROR

The ns declaration for routes/upload.clj includes the following line

[picture-gallery.util :refer [galleries gallery-path]]

however that namespace has not been created yet at this point, so when the next page suggests trying to hit the upload page in a browser you get a big stack trace.

135SUGGEST

The set-config! for the rotor config is a bit confusing. It’s shown first in the file listing, with the timbre/set-config! prefix. Then it’s shown again, but without the timbre/ prefix — and with a full path in the value for the :path key. This section could probably be more clear.

138TYPO

“confuguration” is likely a typo :-)

“This allows us to have less overhead per application and the ability to provide a common >>>confuguration<<< for all the applications deployed on the server.”

26ERROR

When the compiler gets to ‘error’ in the following section of home.clj, it encounters an error:

(defn home []
(layout/common
[:h1 “Guestbook”]
[:p “Welcome to my guestbook”]
[:p error]

The error message: clojure.lang.Compiler$CompilerException
java.lang.RuntimeException: Unable to resolve symbol: error in this context, compiling:(guestbook/routes/home.clj:7:3)

26TYPO

When the compiler gets to ‘message’ in the following section of home.clj, it encounters an error:

(form-to [:post “/”]
[:p “Name:”]
(text-field “name” name)
[:p “Message:”]
(text-area {:rows 10 :cols 40} “message” message)

Error message: clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: message in this context

40TYPO

The output of include-css function contains “/css/reset.css” although we passed “/css/mobile.css” on input.

103TYPO

The text says, “In our save-thumbnail function, we call resource-path to get …”, but the code uses gallery-path, not the resource-path.

56+ERROR

The code snippets are always listed as being in the directory “liberator-snippets/”, while the text clearly states e.g. “Let’s open the liberator-service.routes.home namespace”, or “let’s create a static HTML page in our public directory”. This makes for very confusing code reading, especially since there’s no public directory in the project that was created with `lein new compojure-app …` on p. 56. I was left wondering where to really put the code and HTML.

65SUGGEST

Inside the :exists? decision, the line {::file (file (str (io/resource-path) “/home.html”))} is never explained, and neither is the fact that we’re wrapping both that and the (io/get-resource…) call inside a vector. In the text, all I’m told is “If the file isn’t available then io/get-resource will return a nil”, which seems perfectly enough to do without needing to use both that odd map and a vector around it all.

98+ERROR

using hiccup.util/url-encode, as referred in the ns definition of picture-gallery.routes.upload, will not work for filenames with spaces. The browser will request the image URL with the spaces replaced by + (instead of %20), which file-response won’t handle, and I get a 404 response. Using hiccup.util/percent-encode instead fixes this problem.

39ERROR

It seems that with the latest version of LightTable (0.8.1), the insta repl isn’t bundled by default, but needs to be installed as a plugin.

Categories: