The format of the paragraph is broken until found ~ again.
2018-06-23
66
ERROR
The file where the supervision tree starts the Rumbl.Repo is located in lib/rumbl/application.ex instead of lib/rumbl.ex.
2018-06-23
17
TYPO
“Elixir needs Erlang” says it needs v17 or greater, but hexdocs.pm Guides say v18 or greater. It also seems like Travis only runs tests on v18.3 and up.
2018-06-23
17
TYPO
“Phoenix needs Elixir” says it requires Elixir 1.1 but the Guides on hexdocs.pm say 1.4 or greater.
2018-06-23
69
TYPO
The responses on iex using changeset starts with # instead of %
iex> alias Rumbl.Accounts.User
iex> changeset = User.changeset(%User{username: “eric”},
%{})
Ecto.Changeset{changes:{}, …} #here starts with # instead of %
iex> import Ecto.Changeset
Ecto.Changeset
iex> changeset = put_change(changeset, :username, “ericmj”)
Ecto.Changeset{changes:{username: “ericmj”}, …} #here starts with # instead of %
2018-06-25
82
ERROR
Sample route of endpoint.ex is wrong: lib/rumbl/endpoint.ex should be lib/rumbl_web/endpoint.ex.
2018-06-25
Chris, there are three instances that need to be picked up for this one.
132
ERROR
The text says “Next, let’s share it with the router, like this:” and has a code block starting with ‘scope “/manage”,…’.
A couple paragraphs down, it has the exact same code block, so I think this first code block is not correct.
2018-06-25
136
ERROR
First, a “mix ecto.rollback” is performed.
The text says that the next step is to “migrate back up”, but it says “mix ecto.rollback” again when I think it should say “mix ecto.migrate”. The output also shows “backward” when it should show “forward”.
2018-06-23
139
ERROR
The text says “video = Repo.update!(changeset)” but “Repo” has not yet been aliased.
I believe it should say “video = Rumbl.Repo.update!(changeset)”.
2018-06-23
103
ERROR
In order to pipe through authenticate_user on the router, we need to import the function: lib/rumbl_web/router.ex
import RumblWeb.Auth, only: [authenticate_user: 2]
Then the function will be available to pipe:
pipe_through [:browser, :authenticate_user]
2018-06-25
110
ERROR
When referring to Repo, needs to have Rumbl.Repo as per on the iex session we didn’t define the alias.
Solution: Add alias at the beginning of the iex session as per is used many times.
alias Rumbl.Repo
iex> video = Repo.update!(changeset)
…> |> Repo.update!()
iex> video = Repo.get(Rumbl.Multimedia.Video, video.id)
And in page 111
iex> video = Repo.preload(video, :user)
iex> Repo.one(query)
2018-06-23
133
TYPO
“Comedy” instead of “Comdey”
iex> Repo.all from v in Video,
…> join: u in assoc(v, :user),
…> join: c in assoc(v, :category),
…> where: c.name == “Comdey”,
…> select: {u, v}
2018-06-23
80
ERROR
The registration and creation of users were mentioned on the backend but not on the front end. And in pg. 137 the view has the email and password fields.
This could be added to lib/rumbl_web/templates/user/new.html.eex in some point on the “creating users” section on page: 80 or 81.
+ <%= inputs_for f, :credential, fn i -> %>
+
+ <%= text_input i, :email, placeholder: “Email” %>
+ <%= error_tag i, :email%>
+
+
+ <%= password_input i, :password, placeholder: “Password” %>
+ <%= error_tag i, :password%>
+
+ <% end %>
2018-06-25
40
TYPO
Just like our RumblWeb.Endpoint starts our web server, the Rumb.Repo line ensures
our application startup starts our application Repo. Should be “the Rumbl.Repo line ensures”…
2018-06-19
41
TYPO
We’ll add a couple function which allows user…Should be “We’ll add a couple of functions which allow user”…
2018-06-19
43
OK
I’m coming from Rails, which has strong naming conventions, e.g. controllers are plural, tables are plural, models are singular; the names of classes correspond to the filenames in which you can find them..
It might be good to have a side-bar or footnote here, which discusses the specific naming conventions which Elixir / Phoenix have
2018-07-28
This is probably a good idea. We will look at this as we ready the entire book for production. I am going to leave this one open.
\n
\nWe actually already address this in several places. Marking this fixed.
43
ERROR
There might be an issue with the CSS… the “/users” part of that error message is rendered white on white - invisible
I get the error message:
UndefinedFunctionError at GET
When I select the text, I can see the “/users”:
UndefinedFunctionError at GET /users
function RumblWeb.UserController.init/1 is undefined (module RumblWeb.UserController is not available)
Browser:
Google Chrome\t66.0.3359.181 (Official Build) (64-bit)
Revision\ta10b9cedb40738cb152f8148ddab4891df876959-refs/branch-heads/3359@{#828}
OS\tMac OS X
2018-06-25
chris, I am also going to leave this one for you.
\n
\nThis was a hover styling issue on the plug debugger side. I have submitted a PR to plug to fix :)
45
ERROR
index.html.eex references Routes, but:
UndefinedFunctionError at GET /users
function Routes.user_path/3 is undefined (module Routes is not available)
2018-06-25
You used the phx.new generator for 1.3, which does not introduce the `Routes` alias, where our unreleased 1.4 generator uses the Routes alias. We will update the install instructions to avoid this confusion. Thanks!
56
TYPO
looks like there is unfinished text / improperly formatted text at the end of page 56 and starting on page 57
2018-06-19
57
TYPO
shouldn’t it say “lib/application.ex”, not “lib/rumbl.ex” ?
The supervisor for Rumbl.Repo is already listed in application.ex
2018-06-23
31
TYPO
web/router.ex => lib/hello_web/router.ex
2018-06-23
34
ERROR
There is a mention of the no longer existing web directory.
2018-06-23
62
TYPO
“You’ll see a good example of this policy segregation when your learn about authentication.” should read “You’ll see a good example of this policy segregation when you learn about authentication.” Replace “your” by “you”
2018-06-19
63
TYPO
“These build three input fields and a submit tag.” should read “These build two input fields and a submit tag” since only :name and :username inputs are created.
2018-06-23
108
ERROR
Rolling back twice on this page. The second rollback should be a migrate command. Replace secong rollback with ` mix ecto.migrate`
2018-06-23
80
TYPO
In the following text, simplify should be simplifying:
This new function isn’t very exciting, but as we grow our application, our purpose-built functions will pay dividends by simplify interactions with our controller
2018-06-19
81
ERROR
Statement “Now we should be able to visit://localhost:4000/users/new and create new users with our registration changeset.” requires additional code to be true.
The template for users/new.html needs to have a field added to support entering the email. Also, new users may be created that lack an email once this is done. The users table is populated, but the credentials table is untouched. Validation of the email existence is also not done. Return value of the Accounts.register.user(user_params) call in UserController.create() is {:ok,
%Bernice.Accounts.User{meta: #Ecto.Schema.Metadata<:loaded, “users”>,
credential: #Ecto.Association.NotLoaded<association :credential is not loaded>,
id: 27, inserted_at: ~N[2018-06-02 18:49:44.334380], name: “test12”,
updated_at: ~N[2018-06-02 18:49:44.334388], username: “testusername12”}}
in such a case.
2018-06-25
125
TYPO
“As it has evolved, we place such concepts in concepts to leave controllers as thin and simple as possible.” should read “As it has evolved, we place such concepts in Contexts to leave controllers as thin and simple as possible.”. Replace second “concepts” by “Contexts”.
2018-06-23
103
ERROR
After “sharing” the authenticate_user/2 function with the controller by editing lib/rumbl_web.ex, the book states “Now let’s share it with the router”, and then lists the following text:
———————
relationships/listings/rumbl/lib/rumbl_web/router.change1.ex
———————
scope “/manage”, RumblWeb do
pipe_through [:browser, :authenticate_user]
resources “/videos”, VideoController
end
Given the context of the paragraph, the text should say to edit lib/rumbl_web.ex:
————-
def router do
quote do
use Phoenix.Router
import Plug.Conn
import Phoenix.Controller
import RumblWeb.Auth, only: [authenticate_user: 2] # New import
end
end
Basically, this is an error of omission since the code doesn’t work until the “import RumblWeb.Auth, only: [authenticate_user: 2]” line is added to 2 places in lib/rumbl_web.ex.
Also, this is a typo error because the text (which appears again on the top of page 104) appears in the wrong place.
2018-06-25
112
TYPO
In the sentence near the middle of the page:
“to the new create_video function we wrote in the Media context, like this:”
The word “Media” should be replaced with “Multimedia”
2018-06-23
45
45
ERROR
The book’s code for index.html.eex just has
, but this will not produce output like the book shows on page 47. For that it should be
2018-06-25
The "old" phoenix 1.3 phx.new generator used bootstrap, which uses the table class. The new 1.4 project generator does not use bootstrap in favor of a mostly classless markup. We will update the book instructions to use the unreleased project generator to resolve the confusion. Thanks!
80
ERROR
When the rumble project is modifed to include the use of passwords, the ‘users/new’ form is never updated to allow a user to register with an email/password.
2018-06-25
95
ERROR
The links in the header to no look like they do in the photo. I think there is possibly something wrong with the version of Bootstrap being used or just incorrect HTML/CSS. I’ve run into this problem multiple times throughout the book. Form inputs are another example, they need to be wrapped in form-group divs and the code examples in the book don’t do that.
2018-06-25
81
ERROR
This section of the book is missing the explanation of how you add the email and password form fields so you can create users with credentials through the UI. I think it’s actually a good place to introduce nested form inputs using inputs_for, because I think that is what you need to do to get it working.
2018-06-25
110
ERROR
This section doesn’t tell you to alias Rumbl.Repo, so when you call this:
video = Repo.update!(changeset)
you will get errors that say:
(UndefinedFunctionError) function Repo.get/2 is undefined (module Repo is not available)
Repo.get(Rumbl.Multimedia.Video, 2)
So you either need to alias Rumbl.Repo or refer to Rumbl.Repo fully-qualified
2018-06-23
45
ERROR
At this point in the book, you have covered how to manually create routes. But in this page, you use the link helper with an argument to a named route, which (I think?) isn’t automatically created based on the router code up until this point. Readers who’ve seen other frameworks may understand what’s up, but people who have little experience with routers in other frameworks may be stumped.
2 possible solutions:
1) Change the way the link is coded in the view example so that it doesn’t use the undefined `user_path`
2) Change the routing definition so that `user_path` is defined (but it may be a little early here to introduce resources).
Great work on this version of the book, by the way. Loving it so far.
2018-06-25
`resources "/users"` indeed defines the `Routes.user_path` so it is not an undefined function. Thanks!
51
TYPO
“Don’t worry, though: things will pick up in a hurry.”
Colon out of no where?
2018-06-19
50-51
SUGGEST
Can the book say something about assigns? Or tell me not to worry about it at least? Not talking about it is weird.
Error page:
def template_not_found(template, _assigns) do
layout:
<%= render view_module, view_template, assigns %>
2018-07-28
Bruce, leaving this one to you
45
TYPO
Super minor style detail: code at page 44 includes a empty line between “use” and “alias”, but code at page 45 doesn’t. Cheers!
2018-06-25
103
TYPO
Code for route repeat twice on page 103 and 104. I check several time and they’re the same thing.
relationships/listings/rumbl/lib/rumbl_web/router.change1.ex
scope “/manage”, RumblWeb do
pipe_through [:browser, :authenticate_user]
resources “/videos”, VideoController end
2018-06-23
72
SUGGEST
I have to use the package pbkdf2_elixir at this time because depending on bcrypt_elixir and comeonin don’t let me accomplish the examples in the book with the next error: An error occurred when loading Bcrypt.
“Make sure you have a C compiler and Erlang 20 installed.
If you are not using Erlang 20, either upgrade to Erlang 20 or
use version 0.12 of bcrypt_elixir”
I’m using a Windows 10 with Linux Subsystem and Visual Studio Code
I get the suggestion for replace this package from here:
github from user KronicDeth at project intellij-elixir issues 891
So with the code replacement I get:
defp put_pass_hash(changeset) do
case changeset do
Ecto.Changeset{valid?: true, changes:{password: pass}} ->
put_change(changeset, :password_hash, Pbkdf2.hash_pwd_salt(pass))
_ ->
changeset
end
end
2018-07-28
We have moved to using pbkdf_elixir to avoid the dependency on a compiler. Thanks!
95
ERROR
While updating app.html.eex the code from the file in app.change1.html.eex (cannot post link) causes an error: “function RumblWeb.Router.Helpers.static_push/2 is undefined or private” for css/jss assets; if just inserting the container section as from the book and leaving the original static_path/2 function there is no issue.
2018-06-25
45
OK
There should not be Routes.user_path it just be user_path in the below snippet.
<%= for user <- users do %>
<tr>
<td><b><%= first_name(user) %></b> (<%= user.id %>)</td>
<td><%= link "View", to: Routes.user_path(conn, :show, user.id) %>
<% end %>
2018-07-28
45
OK
In reference to #83303 submitted by me …
I believe the problem is that Phoenix did not generate the same rumbl_web.ex. In my version it did not add “as: Routes” to the alias of RumblWeb.Router.Helpers
So I’m not sure if the code generator needs updating or if the documentation needs correcting. You reference “as: Routes” later on on page 66 I believe but you suggest that it is automatically added for you at site creation.
Snippet pasted below of what my version created.
def controller do
quote do
use Phoenix.Controller, namespace: RumblWeb
import Plug.Conn
import RumblWeb.Router.Helpers
import RumblWeb.Gettext
end
end
2018-07-30
To use the unreleased 1.4 `phx.new` generator, you can install it with: mix archive.install https://github.com/phoenixframework/archives/raw/master/1.4-dev/phx_new.ez
151
TYPO
Under “Testing User Accounts”, in the last sentence of the first paragraph, right before the code block, it says “Crearte a new file…”, with an extra “r”. It should say “Create a new file…” instead.
2018-08-11
161
ERROR
The tests for the “authenticate_by_email_and_pass” section do not work because the setup and test helpers are not correct. I solved them with these changes:
rumbl/test/rumbl/accounts/accounts_test.change1.exs:
setup do
{:ok, user: user_fixture(credential: %{email: email, password: pass})}
end
The “video_fixture” function is missing the “title” attribute. This makes tests from page 163 fail.
2018-07-28
68
TYPO
“On :success , we add a flash message to the conn and then redirect to” (last line on the page)
2018-07-28
0
DEFER
Maybe mentioning IEx.pry, even in a side note, would be helpful for some. The book, especially combined with the official documents, is great, but being able to inspect the parsed request in conn, changeset validation on form submission etc. alongside them helped me a lot. Plus IEx.pry is an Elixir built in.
2019-07-21
Good idea. We'll look at this one.
\n
\nsorry... we are out of time :(
\n
\nNext edition.
66
TYPO
Line 4; “rumbl-web file” should be “rumbl_web file”.
2018-07-28
76
TYPO
Ecto.Changest.cast_assoc
instead of
Ecto.Changeset.cast_assoc
in
Since we’re changing a structure that has elements in two tables, we need Ecto.Changest.cast_assoc .
2018-07-28
110
ERROR
Sorry if this is wrong. I’m still very new.
I believe this line: iex> video = Repo.update!(changeset)
Should be: iex> video = Rumbl.Repo.update!(changeset)
When I attempt to tab complete on the books version most of the methods in the Ecto.Repo documentation don’t show up. When I try the book’s command I get the following error.
iex(17)> video = Repo.update!(changeset)
(UndefinedFunctionError) function Ecto.Repo.update!/1 is undefined or private
(ecto) Ecto.Repo.update!(#Ecto.Changeset<action: nil, changes: %{user: #Ecto.Changeset<action: :update, changes: %{}, errors: [], data: #Rumbl.Accounts.User<>, valid?: true>}, errors: [], data: #Rumbl.Multimedia.Video<>, valid?: true>)
I get the following with my suggested replacement.
I must be misunderstanding this, but “setup” piece doesn’t (and shouldn’t) work with the parameters match like that. If “login_as” tag is unspecified for some test cases, the suite crashes with an error because of no matching setup method found (clearly because the parameter pattern doesn’t match).
Previous version of the book had it right, I think. I wonder how this code works for the authors.
— alg @ elixirforum.com
2018-07-30
28
OK
At the bottom of the page it says that Phoenix will use webpack.js, but the phx.new generator seems to be using brunch instead of webpack.
2018-07-28
We use webpack for 1.4. Closing this one.
49
OK
The css class “phx-hero” used is not defined in the scaffold code, resulting in the rendered welcome page not matching the pictured output.
2018-07-30
To use the unreleased 1.4 `phx.new` generator, you can install it with: mix archive.install https://github.com/phoenixframework/archives/raw/master/1.4-dev/phx_new.ez
56
TYPO
Bottom of page: “You’ve seen template code before, but you’ll walk through it anyway” -> “… we’ll walk through it anyway”
2018-07-28
60
OK
The “common code” uses the tag where previously the tag was used, it should be consistent.
2018-07-28
Good suggestion. Too much effort to fix at this stage.
70
TYPO
“If you’ve seen plenty MVC applications in the past” -> “… plenty of …”
2018-07-28
77
ERROR
Seems like the display of the “New User” form should show the provided input of “Jackie”.
2018-07-28
98
SUGGEST
“Don’t let the init function throw you off. Our plug won’t accept any options at run time. The init macro is simply a way to accept configuration options at compile time.”
This is unclear — where is the init macro? It looks like we’re defining a function here, not a macro.
2018-07-28
105
ERROR
“Create a new web/views/session_view.ex file that looks like this:”
Should be … lib/rumbl_web/views/session_view.ex …
2018-07-28
135
TYPO
where: c.name == “Comedey”
Should be “Comedy”
2018-07-28
121
TYPO
Last sentence, first paragraph under “Adding Categories” is “First, let’s generate the model and migration, using phoenix.gen.model, like this:” Should be “schema” instead of “model” and “phx.gen.schema” instead of “phoenix.gen.model”.
2018-07-28
45
ERROR
The listing for index.html.eex contains two apparent errors:
(1) “Routes.user_path()” should be “user_path()”; if “Routes” is included, it creates an error.
(2) The table tag needs a table class, too, to pick up the pretty table styling that the book shows, i.e.:
. (I don’t know if this is a bug in the book or a bug in the table styling in Phoenix’s default app.css file.)
2018-07-28
\nwe changed our css to be classless and the routes alias was added in the new generators.
127
TYPO
Second paragraph, second sentence, “orsder” is misspelled.
2018-07-29
131
TYPO
First paragraph, fourth sentence, “another” is misspelled “anther”.
2018-07-28
117
ERROR
“Fill out the form and click “Submit”. You see a list of your new videos, just as you should."
I don’t see a list of videos — what I actually see is a detail page for the submitted video, localhost:4000/videos/1.
2018-07-28
122
ERROR
When I `alias Ecto.{Changeset, Repo} and then run `video = Repo.update!(changeset)` I get an error. I think it’s supposed to be `video = Rumbl.Repo.update!`
2018-07-28
130
ERROR
“First, let’s generate the model and migration, using phoenix.gen.model, like this”
The code makes it look like it should be “phoneix.gen.schema”?
2018-07-28
136
TYPO
“to fetch the data in the orsder we want”.
2018-07-28
90
SUGGEST
After the update to RumblWeb.UserController, it might be a good idea to include the changes needed to lib/rumbl_web/templates/user/new.html.eex to add credential-related fields, as credentials is not directly accessible via the f argument:
scope “/manage”, RumblWeb do
pipe_through [:browser, :authenticate_user]
resources “/videos”, VideoController
end
I believe the code in this part should be:
def router do
quote do
use Phoenix.Router
import Plug.Conn
import Phoenix.Controller
import RumblWeb.Auth, only: [authenticate_user: 2] # New import
end
end
2018-10-13
125
SUGGEST
The interplay between the router and the injected action/2 is not very clear in the text (router does not call index/show/edit/etc directly; router calls action/2 which calls those functions); maybe adding the excellent explanation from the section “Overriding action/2 for custom arguments” in Phoenix.Controller documentation can sled more light in how it is used (by default).
2019-06-07
155
163
ERROR
I had to add this line to the video_fixture function in test_helpers to let the video desc section in multimedia_test.exs go through ok.
attrs =
Enum.into(
attrs,
%{
url: “…”,
# add title field to map.
title: “a title”,
description: “a description”
}
)
2018-07-28
112
ERROR
iex> video = Repo.update!(changeset)
%Rumbl.Multimedia.Video{…}
Throws an error. Shouldn’t it be
iex(8)> video = Rumbl.Repo.update!(changeset)
[debug] QUERY OK db=0.9ms
2018-07-28
144
TYPO
The word “comedy” in the example that shows queries with associations is wrongly spelt as “Comedey” (with an extra ‘e’).
2018-07-28
145
SUGGEST
Prior to the definition of “constraint error,” there was no example/demo showing the result of adding a duplicate category. Probably need to reword the definition to forward reference the duplicate username error demonstration on PDF page 146 instead.
2018-07-29
Tough call. We're going to leave this one as is.
162
ERROR
To get the test “lists all user’s videos on index”, %{conn: conn, user: user} do test to work, I had to annotate with a @tag, just like in previous version, to force the login_as key into the config map passed into each test, so something like:
@tag login_as: “max”
test “lists all user’s videos on index”, %{conn: conn, user: user} do
Without this, I get following error:
(FunctionClauseError) no function clause matching in ELSWeb.VideoControllerTest.__ex_unit_setup_1/1
…
I also had to change the line:
assert html_response(conn, 200) =~ ~r/Listing videos/
to:
assert html_response(conn, 200) =~ ~r/Listing Videos/
2018-07-30
45
TYPO
On template listiing, it shows:
`
<%= link “View”, to: Routes.user_path(@conn, :show, user.id) %>
`
But in the new version of Phoenix, it should be just user_path.
Also on page 47, the `rumble_web.ex` snippet` should be updated. It currently shows:
`alias RumblWeb.Router.Helpers, as: Routes`
Where as the default snippet is `import RumblWeb.Router.Helpers`
2018-07-28
Use a newer 1.4 beta please.
74
85
ERROR
`null: false` is not included in the sample code :
i assume that it should be there because the explanation text says the following :
“Likewise, we shouldn’t allow credentials without users, so we also passed null: false.”
2018-07-30
127
TYPO
We added a Multimedia.list_alphabetical_categories to fetch the data in the orsder we want.
Should be: order
2018-07-28
49
ERROR
Under “Naming Conventions”, the inferred template directory is listing the Phoenix <=1.2 Location of “web/templates/user” but it should be “lib/rumbl_web/templates/user”.
2018-07-28
149
ERROR
The video_fixture function needs a title, otherwise tests of pages 155/6 will fail because title is a required parameter, as defined in changeset function of page 139.
So the function video_fixture of page 149 can be:
def video_fixture(Accounts.User{} = user, attrs \\\\{}) do
attrs =
Enum.into(attrs, %{
url: “some hyperlink not allowed in the errata”,
title: “some test title”,
description: “a description”
})
{:ok, video} = Multimedia.create_video(user, attrs)
video
end
2018-07-30
157
ERROR
The user_fixture function does not match with source code given and results in a compilation error.
2018-07-30
28
SUGGEST
In the `Phoenix needs Elixir` section, it is stated at the end “That means you’ll have to install Node.js.”, but right next to it you drop to PostgreSQL, and then Node. You might want to fix this.
2018-07-29
156
SUGGEST
for the test “GET /”
I’d like to know how
conn = get conn, “/”
is dealt with, what files are involved with this, where that get conn is translated
2018-07-29
Good idea but not this beta. We will keep this open to consider it.
173
SUGGEST
assert_error_sent comes from nowhere.
You could point to hexdocs.pm/phoenix/Phoenix.ConnTest.html and give some explanation, what parameters can be used apart from :not_found, etc
2018-07-29
123
113
ERROR
iex> Repo.one(query)
should be
iex> Rumbl.Repo.one(query)
2018-07-28
179
171
ERROR
What you have in the code is different from what is shown in the book.
In order for `mix test test/rumbl_web/controllers/auth_test.exs to pass all nine tests, one have to change the file test/support/test_helpers.ex, so that it resembles what you provide in the code that supports the book:
email: attrs[:email] || “#{username}@localhost”
password: attrs[:password] || “supersecret”
2018-07-30
38
OK
The code example on this page makes use of the CSS class ‘phx-hero’. Following along with Phoenix v1.3.3, this code example does not match the image shown underneath on the same page. It appears as if that CSS class has been renamed to ‘jumbotron’ in more recent versions of Phoenix.
2018-07-30
To use the unreleased 1.4 `phx.new` generator, you can install it with: mix archive.install https://github.com/phoenixframework/archives/raw/master/1.4-dev/phx_new.ez
39
ERROR
The code example which shows ‘lib/rumbl/application.ex’ does not match the code as generated by more recent versions of Phoenix (v1.3.3). Specifically, the code example says ‘Rumbl.Repo’ whereas, in the latest version of Phoenix, this is passed as a parameter to ‘supervisor()’, like so: ‘supervisor(Rumbl.Repo, [])’
2018-07-30
The phoenix 1.4 generators use the new child spec style, so the book is correct. To use the unreleased 1.4 `phx.new` generator, you can install it with:
\n
\nmix archive.install https://github.com/phoenixframework/archives/raw/master/1.4-dev/phx_new.ez
\n
45
ERROR
The code example on this page does not compile. ‘Routes.user_path(conn, :show, user.id)' should be 'user_path(conn, :show, user.id)’. Also, the CSS class ‘table’ is missing from the table in ‘index.html.eex’ so that the code example does not produce the same visual appearance as the image shown on page 47.
2018-07-28
Use a newer Phoenix beta please.
49
SUGGEST
In the prose on page 49, there is reference to the code example, but I think the references are incorrect. For example, in this sentence: “When Phoenix renders templates from a controller, it infers the name of the
view module, Rumbl.UserView , from the name of the controller module, Rumbl.UserController .” - Shouldn’t it be ‘RumblWeb’ and not ‘Rumbl’?
2018-07-28
Good catch
49
SUGGEST
There are several places in the book which clarifies that views are just modules and templates are just functions, for instance on page 49. The clarification is definitely useful, but I find it somewhat difficult to “map” these synonymous terms in my head and follow along when they are used interchangeably. Perhaps the it would be easier to follow along if your stick with one term or the other. Personally, if views are just modules and templates are just functions, I would prefer to use the most basic terms; ‘module’ and ‘function’ - There is no need to jump back and forth between synonymous terms in my opinion.
2018-07-28
Let's see what editors say about consistency and style here.
51
ERROR
The code example on page 51 no longer corresponds to the code generated by more recent versions of Phoenix. For example, in the book, we can see two paragraphs within the ‘main’ HTML tag, which are no longer present in the code generated by Phoenix (in Phoenix v1.3.3, only ‘<%= render view_module, view_template, assigns %>’ remains within the ‘main’-tags, and the other stuff has been moved out in-between the ‘body’-tags).
2018-07-28
The code is correct for the unreleased phoenix 1.4 `phx.new` generator. You can install the unreleased generator with:
\n
\n$ mix archive.install https://github.com/phoenixframework/archives/raw/master/1.4-dev/phx_new.ez
\n
52
SUGGEST
In the summary of chapter 3, you might want to consider including the part about making using of nested templates to avoid duplication. I think that would be a valuable aspect to warrant pointing out in the summary.
2018-07-28
Good idea, but I think we need to let this wait until next release.
9
SUGGEST
This is a minor, subjective style suggestion. The phrase “Here’s the kicker.” is used both on page 4, and shortly thereafter on page 9. Since the phrases are used twice so close to each other, it stood out to me as repetitive. You might want to consider using it only once.
2018-07-28
53
SUGGEST
To be more explicit and to avoid possible term equivocations in the reader’s mind, consider changing the sentence “Ecto is the Elixir framework for persistence” to “… framework for data persistence” or “… framework for persisting data.”
2018-07-28
57
OK
Code example does not correspond to code generated by more recent version of Phoenix. ‘Rumbl.Repo’ should be ‘supervisor(Rumbl.Repo, [])’, etc.
2018-07-28
Please use the updated generators. The code is correct as listed.
59
TYPO
In this sentence: “With our repo calls in place, were ready to try it out even though we haven’t touched our controller code at all.”
‘Were’ should be ‘we’re’.
2018-07-28
59
OK
This is a subjective suggestion; just a matter of taste.
In some places, the text is telling the reader what they are thinking. For example, in this sentence on page 59: “You can already see the benefits of our Accounts context in action.”
As a reader, I find it off-putting when I’m told directly what I’m seeing, hearing or thinking. What if I’m a reader who’s not seeing that?
The authors might want to consider rephrasing such sentences by using the pronoun ‘we’ instead of ‘you’, to soften it up a bit.
2018-07-28
Thanks for the suggestion. Let's see what the editors say.
63
ERROR
The code example on page 63 causes an error. ‘Routes.user_path(conn, :create)' should be 'user_path(conn, :create)’.
2018-07-28
Use a newer beta version please.
66
ERROR
The resulting form from the code example does not match the picture shown in the book on page 66, because the CSS classes are missing from the code example in ‘new.html.eex’.
2018-07-30
The template is correct since the new 1.4 generators use a different, classless css setup
17
ERROR
In the output for calling ‘elixir -v’ it shows as Elixir 1.1.0. This should say something newer like 1.4 or later
setup do
{:ok, user: user_fixture(%{credential: %{email: email, password: pass}})}
end
If not, then tests fail with:
1) test authenticate_by_email_and_pass/2 returns unauthorized error with invalid password (Rumbl.AccountsTest)
test/rumbl/accounts/accounts_test.exs:73
(MatchError) no match of right hand side value: {:error, #Ecto.Changeset<action: :insert, changes: %{name: “Some User”, username: “user2244”}, errors: [credential: {“can’t be blank”, [validation: :required]}], data: #Rumbl.Accounts.User<>, valid?: false>}
stacktrace:
test/test_helper.exs:13: Rumbl.TestHelpers.user_fixture/1
2018-07-30
153
161
ERROR
Invalid attrs passed to the user fixture will cause the tests to fail.
In the book :
setup do
{:ok, user: user_fixture(email: email, password: pass)}
end
It should be :
setup do
{:ok, user: user_fixture(credential: %{email: email, password: pass})}
end
2018-07-30
75
DEFER
A deeper explanation on how the references function works would be nice: even after reading Chapter 6 I felt a bit lost without reading further documentation. Thanks.
2019-01-23
Good comment. We'll take a look at this one after we have completed the chapters and are readying for production based on the other comments.
74
ERROR
Shouldn’t :user_id also have null: false? or is the following referring only to :password_hash
> Likewise, we shouldn’t allow credentials without users, so we also passed null: false .
2018-10-13
146
OK
Page 146 of the epub: Inconsistent use of Comeonin.Bcrypt and Comeonin.Pbkdf2
Code section in book “authentication/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex” is using Comeonin.pbkdf2.checkpw in the first cond, and comeonin.bcrypt.dummy_checkpw() in the block of the third cond.
2018-08-13
The purpose is for misses not to take a predictable length of time; it doesn't need to match.
Good thinking, but the user_fixture function is actually a convenience function that takes a credential like this:
\n
\ndef user_fixture(attrs \\\\ %{}) do
\n username = "user#{System.unique_integer([:positive])}"
\n {:ok, user} = attrs
\n |> Enum.into(%{
\n name: "Some User",
\n username: username,
\n credential: %{
\n email: attrs[:email] || "#{username}@example.com",
\n password: attrs[:password] || "supersecret", }
\n })
\n |> Accounts.register_user()
\n user
\nend
57
SUGGEST
The text says “… in our application’s supervision tree in lib/application.ex, like …”. I was confused until I realized that actually meant “lib/rumbl/application.ex”. I think other new users to Phoenix might appreciate this change, as some (like me) might be left wondering “am I supposed to create `lib/application.ex`?”
2018-08-13
111
TYPO
In the example code to create a new video you need a space in description:“new video”. Should be description: “new video”
2018-08-11
117
TYPO
last word on the page: visting. Should be visiting
2018-08-11
44
TYPO
defmodule RumblWeb.UserController do
use RumblWeb, :controller
should be: RumbleWeb.UserController do
use RumbleWeb, :controller
2018-08-12
45
TYPO
RumblWeb -> RumbleWeb
2018-08-11
Rumbl is the name of the app. It's correct as listed.
47
TYPO
RumblWeb -> RumbleWeb
2018-08-11
49
TYPO
RumblWeb -> RumbleWeb
2018-08-11
45
OK
I have to apologize for my typos corrections.
All my remarks that Rumble - Rumble are false, because I created the system with: mix phx.new rumble !!!!
third line:
supervision tree in lib/application.ex, like this:
should probably be:
supervision tree in lib/rumbl/application.ex, like this:
2018-08-13
83
TYPO
“We have seen both kinds of plugs in use. From the endpoint module in lib/rumbl/endpoint.ex, you can see an example of a module plug:”
the path should probably say: lib/rumbl_web/endpoint.ex
2018-10-13
191
TYPO
Module is defined on previous page as Rumbl.Multimedia.Permalink but aliased as Rumbl.Permalink.
2018-10-13
153
OK
Compilation error in file test/rumbl/accounts/accounts_test.exs ==
(CompileError) test/rumbl/accounts/accounts_test.exs:7: undefined function describe/2
I don understand this compilation error.
I am running: elixir v1.6.4 and Phoenix v1.2.5
2018-08-13
If anyone else is getting this I will reopen.
171
ERROR
user = user_fixture(username: “me”, email: “me@test”, password: “secret”)
Should be
user = user_fixture(username: “me”, credential: %{email: “me@test”, password: “secret”})
It throws an error without credentials: %{}
2018-10-13
59
TYPO
$ mix phx.server
[info] Running HelloWeb.Endpoint with Cowboy on
HelloWeb.Endpoint should be RumblWeb.Endpoint
2018-10-13
59
SUGGEST
After issuing the html command localhost:4000/users/ I got the error message
function Routes.user_path/3 is undefined (module Routes is not available).
I had two versions with the same error message: (elixir 1.6.4, Phoenix v1.2.5) and ( elixir 1.7.0, Phoenix 1.3.4) I don have the faintest idea what caused the problem. It seems I have to read the ebook without doiing the exercises. It is frustating!
2018-10-18
264
TYPO
B4 is missing new chapter on channels
2018-09-09
81
ERROR
From what I can tell, we need to update the Rumbl.Accounts.change_user methods here too. Otherwise the usage of inputs_for in the template raise an error about missing the “key: :credential” when we attempt to render the /users/new.
This is what I came up with:
defmodule Rumbl.Accounts do
def change_user(%User{} = user) do
User.registration_changeset(user, %{credential: %{}})
end
end
It may not be quite the correct fix, but it got me unstuck. Hopefully the next person won’t be derailed by this.
> Likewise, we shouldn’t allow credentials without users, so we also passed null: false to the add :user_id column
To me this reads as though the snippet is incorrect (admittedly I am new to Elixir and Ecto migrations).
(The same is also true for the file phoenix14/code/authentication/listings/rumbl/priv/repo/migrations/20180410050016_create_credentials.change1.exs)
2018-10-18
107
SUGGEST
Fill out the form and click “Submit” should not that be Fill out the form and click “Save”?
2019-01-21
49
TYPO
When Phoenix renders templates from a controller, it infers the name of the
view module, RumblWeb.UserView , from the name of the controller module, Rum-
bl.UserController.
Controller name should be RumblWeb.UserController
2018-10-13
105
TYPO
Comeonin.Bcrypt.dummy_checkpw() should be Comeonin.Pbkdf2.dummy_checkpw()
2018-10-13
156
ERROR
I have an error when coding the following:
key :show not found in: [index: []]
<%= link “View”, to: Routes.user_path(@conn, :show, user.id) %>
This is in chapter 3, Coding Views
2018-10-13
156
SUGGEST
Phoenix has a feature to reload only for eex files, but if it is changed in some .ex file, the change will be made when you rerun the server. It took me some time to find out. This is with respect to my previous post.
2018-10-13
156
SUGGEST
The changes are automatic, but if I remove router.ex get “/ users /: id”, UserController,: show, the server is reloading, and it continues to work, but when I restart the server it throws an error. Do not reload the changes only in the router.ex file
2018-10-13
127
TYPO
in authenticaion/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex it says:
“Comonin.Bcrypt.dummy_checkpw()”
Shoudln’t this be :
“Comonin.Pbkdf2.dummy_checkpw()” ?
2018-10-13
78
SUGGEST
It wasn’t clear to me that the book’s intention was for me to type
alias RumblWeb.Router.Helpers, as: Routes
It read to me like I should expect to see it there already (which I did not).
I added it manually and got the form to work.
2018-10-13
58
ERROR
Error in the change for ecto/listings/rumbl/lib/rumbl/accounts/accounts.change1.ex
Unless I missed something, it looks like you forgot to alias Rumbl.Accounts.User in the file. So the file should be:
alias Rumbl.Repo
alias Rumbl.Accounts.User
Without this line I am getting an error:
Protocol.UndefinedError at GET /users
protocol Ecto.Queryable not implemented for User, the given module does not exist. This protocol is implemented for: Atom, BitString, Ecto.Query, Ecto.SubQuery, Tuple
Hope this helps!
2018-10-13
Chris, can you verify? I think this is an error from an earlier Phoenix install, correct?
\n
83
ERROR
Line 4 says ‘lib/rumbl/endpoint.ex’ it should be ‘lib/rumbl_web/endpoint.ex’
2018-10-13
89
ERROR
Nothing important. Just a little thing.
In the book it says “Now let’s plug it in our controller, right after use Rumbl.Web:”
but in the code it’s right after “alias Rumbl.Accounts.User”
2018-10-13
46
TYPO
In the blue Chris call out box, the link at the end is broken. It should be: (protocol removed and space inserted due to hyperlinks not being allowed) www.evanmiller. org/elixir-ram-and-the-template-of-doom.html
2018-10-13
93
ERROR
accounts.change2.ex is using Comeonin.Bcrypt.dummy_checkpw to prevent timing attacks, yet the rest of the application is using PBKDF2, which I think it probably has a distinct time signature, so shouldn’t we use Comeonin.Pbkdf2.dummy_checkpw instead? Thanks.
2018-10-13
60
TYPO
“We then pass the cast function a list of fields to tell Ecto that name and username are allowed to be casted as user input.”
Shouldn’t “casted” be “cast”?
2018-10-13
65
TYPO
“Add a create function toUserController:” needs a space between “to” and “UserController”.
2018-10-13
28
ERROR
Wouldn’t be “lib/hello/application.ex” instead of “lib/hello.ex”?
PDF Page 28
“Each Mix project also has a lib directory. Support for starting, stopping, and supervising each application is in lib/hello.ex.”
Reasoning:
PDF Page 32
“You can see two top-level files, hello.ex and hello_web.ex. The Hello module is an empty module which defines the top-level interface and documentation for your application.”
2018-10-13
124
ERROR
From the online example file:
/titles/phoenix14/code/queries/listings/rumbl/lib/rumbl/multimedia/multimedia.change1.ex
‘alias Rumbl.Multimedia.Category’ is on both line 22 and 28 ;-)
2019-01-21
64
ERROR
‘’
Should be
‘’
Doc also states that it creates a button.
2018-10-13
147
TYPO
Space missing ‘thetest/rumbl/accounts’ should be ‘the test/rumbl/accounts’
2018-10-13
93
ERROR
The “true” case in the “cond” in function “authenticate_by_email_and_pass” calls “Comeonin.Bcrypt.dummy_checkpw()”, but the book doesn’t install bcrypt_elixir. Changing to “Comeonin.Pbkdf2.dummy_checkpw()” fixes it.
2018-10-13
153
ERROR
Test failure:
Comeonin.Bcrypt.dummy_checkpw/0 is undefined (module Comeonin.Bcrypt is not available)
adding {:bcrypt_elixir, “~> 1.0”} in the mix.exs file solved the problem
System info
OS X High Sierra 10.13.5
Erlang/OTP 20
Phoenix v1.4.0-dev
2018-10-13
94
ERROR
When I try to create a new user, I get this error:
function Comeonin.Pbkdf2.hashpwsalt/1 is undefined (module Comeonin.Pbkdf2 is not available)
I checked all the code from the chapter and everything seems to be fine.
Thanks!
2018-10-13
I think you missed adding the dependency.
29
OK
It would be nice to not force people (specially new ones to tech) to install Postgres locally, you can suggest:
1. Installing docker
2. Run a command like docker run —name rumbl_dev —volume rumbl_dev:/var/lib/postgres/data/rumbl_dev -p 5432:5432 -e ‘POSTGRES_DB=rumbl_dev’ -e ‘POSTGRES_USER=postgres’ -e ‘POSTGRES_PASSWORD=postgres’ postgres:10.5
3. Suggest running ` docker start rumbl_dev
Thanks!
2018-10-13
Ironically, the magic of Docker is just too much to learn here, and too much for the author team to support across platforms. We are going to go with a more basic approach without the technical burden of learning another stack.
\n
\nGood idea, but we can't really do this.
112
SUGGEST
“Relational databases like Postgres are named that way for a reason. Dealing
with related data is the defining characteristic of that whole family of
databases, so management of relationships is the feature that makes or breaks
any persistence layer. ”
This is a common misconception, relational databases aren’t named that way because they manage relationships, but because the data is stored in relations(sets of tuples) as in Codd’s relational model.
2019-01-21
96
TYPO
name -> username
“If the user is available, we show the name, followed by a logout link.”
2018-10-13
121
TYPO
“First, let’s generate the schema and migration, using phoenix.gen.schema, like this:”
phoenix.gen.schema => phx.gen.schema
2019-01-21
106
TYPO
“The up migration…” (last paragraph on page). ‘up’ seems out of place. Should be “The CreateVideos migration” or simply “The migration”
2019-01-21
136
TYPO
“The Ecto.ConstraintError, which you saw when we tried to add a category twice.”
The ConstraintError is actually shown for the first time on the next page. It’s not encountered while adding categories (the create_category function even prevents it from happening ;-)).
2018-10-13
162
ERROR
In the line “conn = get conn, video_path(conn, :index)”, ‘video_path’ must be prefixed with Routes.
This also applies to the code listed in video_controller_test.change1.exs (line 24)
2019-01-21
67
TYPO
Hi,
First of all: great material, keep up your awesome work.
I may have found a little inconsistency. In the following paragraph you find the key(?) :success that is not used in the listing. This Couleur be reworked into :ok or plain success.
Easy enough. We insert the new user record and then match on the return code. On :success, we add a flash message to the conn and then redirect
2018-10-13
79
67
TYPO
Bottom of page says “On :success, we add a flash message…” where perhaps it should read “On :ok, we add a flash message…”
2018-10-13
79
ERROR
Minor technical error at the bottom - need to alias Rumbl.Accounts.User in the iex session prior to running the credential fixup look
2018-10-13
83
TYPO
The Anatomy of a Plug…
We have seen both kinds of plugs in use. From the endpoint module in
lib/rumbl/endpoint.ex, you can see an example of a module plug:
Should be: lib/rumbl_web/endpoint.ex. So the RumblWeb module, not the Rumbl module
2018-10-13
65
ERROR
LINQ is not a persistence framework. A better comparison for Ecto in. NET would be to Entity Framework
2018-10-13
211
TYPO
|> Annotation.changeset() should be |> Annotation.changeset(attrs)
Otherwise the test on page 213 won’t work.
2018-10-13
218
SUGGEST
Not only ‘this.scheduleMessages’ runs forever even when it’s empty but also every time it joins a channel it will call a new ‘this.scheduleMessages’.
It means that after 5 joins we will end up with 5 ‘setTimeout’ running and each will call ‘this.scheduleMessages’ that will run forever.
After a considerable amount of joins it could become problem.
2019-01-23
1
OK
This is a pretty hefty set of feedback, but the organization of the book seems a little off. It digs really deep into the theory of phoenix before people are dragged into the programming enough to care about that stuff yet.
Organization that would be super handy:
The whole book should be 1 example website that we’re creating as a group, in a test driven way. Using all the generators and everything that phoenix provides. As you go the book should give more and more details of why different things work the way they do (rather than dumping that all into chapter 2) and how the pieces put together. In the end we should have a complete example that is a real website with most everything that people will use creating websites (login, oauth, admin panels, channels, etc) complete with some details on how to deploy.
I recognize that this is a complete rework of the book, but I feel like it would bring a lot more adoption to phoenix (much like the original rails book that did the same)
2018-10-13
Good ideas, but we can't really act on feedback like this in a second generation best selling book. But I will keep your comments in mind for other books I edit in the series!
\n
\nWe did try a test-first approach, but found it too repetitive, and found the test theory distracting from the primary concepts. It's not the best way to *code* phoenix, but may be a better way to *teach* phoenix apps.
\n
211
ERROR
On line 5 of the first code block, it should be Annotation.changeset(attrs) and not Annotation.changeset()
It’s actually like this in the downloadable source code but not in the book!
If this isn’t the case, then attrs variable is unused and a nonexistent changeset/1 function is called, which breaks the feature.
2018-10-13
72
ERROR
Hey all,
Just wanted to let you know that the code as it stands for Authentication will not work if you try to use `Comeonin.Bcrypt later on in the book because you now need to add {:bcrypt_elixir, “~> 1.0”} to your dependencies. As of now, the book fails to mention that this dependency needs to be added to the Mixfile. If you dont add this dependency, you’ll get an error that `Comeonin.Bcrypt.dummy_checkpw/0 is undefined because the Comeonin.Bcrypt module is unavailable. So it looks like you need the native elixir bcrypt dependency to compile so that comeonin knows to include it as a module.
2018-10-13
49
TYPO
Does this paragraph:
The view modules infer their template locations from the view module name. In our example, our Rumbl.UserView would look for templates in the web/templates/user/ directory.
Need to read as the following?
The view modules infer their template locations from the view module name. In our example, our RumblWeb.UserView would look for templates in the rumbl_web/templates/user/ directory.
Changes:
‘Rumbl.UserView’ to ‘RumblWeb.UserView’
and ‘web/templates/user/’ to ‘rumbl_web/templates/user/’
2018-10-13
49
TYPO
Does this paragraph:
The view modules infer their template locations from the view module name. In our example, our Rumbl.UserView would look for templates in the web/templates/user/ directory.
Need to read as the following?
The view modules infer their template locations from the view module name. In our example, our RumblWeb.UserView would look for templates in the rumbl_web/templates/user/ directory.
Changes:
‘Rumbl.UserView’ to ‘RumblWeb.UserView’
and ‘web/templates/user/’ to ‘rumbl_web/templates/user/’
2018-10-13
49
ERROR
Does this paragraph:
The view modules infer their template locations from the view module name. In our example, our Rumbl.UserView would look for templates in the web/templates/user/ directory.
Need to read as the following?
The view modules infer their template locations from the view module name. In our example, our RumblWeb.UserView would look for templates in the rumbl_web/templates/user/ directory.
Changes:
‘Rumbl.UserView’ to ‘RumblWeb.UserView’
and ‘web/templates/user/’ to ‘rumbl_web/templates/user/’
2018-10-13
93
ERROR
page 93 on the page, 105 in my pdf viewer
authentication/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex says to add Comeonin.Bcrypt.dummy_checkpw() but since we were previously instructed to install Comeonin.Pbkdf2, Comeonin.Bcrypt is not available, and fails. Should be Comeonin.Pbkdf2.dummy_checkpw().
Thanks!! Enjoying the book.
2018-10-13
93
ERROR
page 93 on the page, 105 in my pdf viewer
authentication/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex says to add Comeonin.Bcrypt.dummy_checkpw() but since we were previously instructed to install Comeonin.Pbkdf2, Comeonin.Bcrypt is not available, and fails. Should be Comeonin.Pbkdf2.dummy_checkpw().
Thanks!! Enjoying the book.
2018-10-13
105
ERROR
page 93 on the page, 105 in my pdf viewer
authentication/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex says to add Comeonin.Bcrypt.dummy_checkpw() but since we were previously instructed to install Comeonin.Pbkdf2, Comeonin.Bcrypt is not available, and fails. Should be Comeonin.Pbkdf2.dummy_checkpw().
Thanks!! Enjoying the book.
2019-01-21
77
65
SUGGEST
I was a bit surprised to encounter the use of the term “model”, since models as a concept has not been discussed much in the book. I was not really sure what this was referring to specifically, so I just took it as a general observation.
> The controller shouldn’t care about these short persistence details, but neither should the model.
It would be nice if this was clarified. Thanks for a great book so far!
in /rumbl/lib/rumbl_web/controllers/user_controller.change3.ex, when I make an error, the url changes from / users/new to /users/
2018-10-13
58
ERROR
The new accounts.ex file seemingly removes the “alias Rumbl.Accounts.User” which causes an error. Consider adding the line there in the example so that it’s more obvious what’s being changed
2019-01-19
198
191
TYPO
When typing the sample IEx session as-is, the following error occurs:
iex> P.cast(“1”)
(UndefinedFunctionError) function Rumbl.Permalink.cast/1 is undefined (module Rumbl.Permalink is not available)
Rumbl.Permalink.cast(“1”)
There’s a typo in the module reference: the “Multimedia” part is omitted. It should be `alias Rumbl.Multimedia.Permalink, as: P`
2018-10-13
86
ERROR
Currently, the text claims that response codes 400-499 are not-found and 500+ is for errors. In reality, only response code 404 is not found. Codes 400-499 are for client errors and codes 500+ are for server errors.
2018-10-13
48
OK
The id param on the show method is a string and is causing me errors.
I had to rewrite the function to
def show(conn, %{“id” => id}) do
int_id = String.to_integer(id)
user = Accounts.get_user(int_id)
render(conn, “show.html”, user: user)
end
2018-10-18
Chris, can you confirm?
19
OK
OTP 19
elixir 1.6 (per book)
node 5.3.0 (per book)
npm 3.3.13 (whatever came with 5.3.0 nodejs)
mixed in phx_new 1.4-dev (per book)
ran “mix phx.new hello”
console reports “ (Mix) The task ”phx.new" could not be found"
2018-10-13
Please see https://github.com/phoenixframework/phoenix/issues/2404
86
SUGGEST
You casually make reference to a session without really introducing the concept. Would be useful for users to have more detail here.
2019-01-21
Interesting observation. We'll take a look after we get through the new chapters.
86
OK
Is there a best practice in terms of file location for storing plugs? Perhaps a plugs directory instead of in controllers?
2018-10-13
105
93
TYPO
We installed Comeonin with Pbkdf2, yet Comeonin.Bcrypt.dummy_checkpw() is used in the authentication/listings/rumbl/lib/rumbl/accounts/accounts.change2.ex file. Should it not be Comeonin.Pbkdf2.dummy_checkpw() instead?
2019-01-21
182
TYPO
lib/rumbl_web/templates/layout.html.eex should be lib/rumbl_web/templates/layout/app.html.eex
2018-10-18
437
ERROR
In the code listed on the page:
media.pragprog.com/titles/phoenix14/code/channels/listings/rumbl/lib/rumbl/multimedia/multimedia.change1.ex
The call in annotate_video to Annotation.changeset is not passing in attrs.
2018-10-13
87-89
SUGGEST
Module vs. Function Plugs.
Newbie here.
More of a discussion here would be useful. I note you choose to use a module plug which gives a lot of flexibility, put also implies a single function per module. So if used in the router pipeline, you end up with:
:a
:b
:c
RumblWeb.Auth (implies a single plug, but a module can contain many functions - is there a reason for this?)
Why not have the module Auth define two functions: currentUser and authenticate?
That way, the above would be
:a
:b
:c
:current_user (In the Auth module)
:authenticate (In the Auth module)
Follows what appears to be the idiomatic norm of sequencing. You check if current_user exists and then you check if that current_user needs to be present in order to visit a page, either on a controller or router pipeline level.
2018-10-13
We may address this a bit later.
41
SUGGEST
I am a little bit troubled that the file `lib/rumbl/accounts/accounts.ex` contains the module `Rumbl.Accounts` while, one page above, `lib/rumbl/accounts/user.ex` contains a module `Rumbl.Accounts.User`.
Is this intentional, and if so, maybe would be nice to give a rationale on this, especially as the explanation at page 42 seems to underline what I am saying.
2018-10-13
Good question. In this setting, Account is the context, and User is the schema.
74
SUGGEST
The copy of the generator output ends with the generator’s instruction to run `mix ecto.migrate` - it seems that this is an instruction from the author which is confusing because you then go on to edit the migration, etc.
Maybe either truncate the pasted output from the generator, or at least change the background or text color or something so it’s clear that it’s not instructions.
2018-10-13
74
SUGGEST
The copy of the generator output ends with the generator’s instruction to run `mix ecto.migrate` - it seems that this is an instruction from the author which is confusing because you then go on to edit the migration, etc.
Maybe either truncate the pasted output from the generator, or at least change the background or text color or something so it’s clear that it’s not instructions.
2018-10-13
83
ERROR
This:
From the endpoint module in lib/rumbl/endpoint.ex
Should be this (I think)
From the endpoint module in lib/rumbl_web/endpoint.ex
2018-10-13
91
TYPO
Assuming you switched from Bcrypt to use Pbkdf2 via comeonin. Page 91 has Pbkdf2 for checkpw but Bcrypt for dummy_checkpw.
2018-10-13
81
ERROR
In addition to changing the create action to use the Accounts.register_user/1 method to generate the proper changeset, the new action also needs to have a proper changeset generated to render the form properly.
Something like adding the following to Rumbl.Accounts and using it in the new action:
def new_user(%User{} = user) do
User.registration_changeset(user, %{})
end
2019-03-15
48
SUGGEST
The grammar seems a bit off here:
“Add that to lib/rumbl_web/templates/user/show.html.eex:”
This would be more correct to say:
“Add this to lib/rumbl_web/templates/user/show.html.eex:”
Since the example to add comes after the statement in question.
2018-10-13
54
SUGGEST
Is this necessary here?
“We’re going to use Ecto’s default database adapter, PostgreSQL. Install Post- greSQL, consulting the Postgres homepage1 for details if necessary.”
I feel pretty confident that the reader could not have followed along to this point without getting many errors. Early on, on page 17, we were already told to install PostgreSQL.
My suggestion is to remove this bit about installing PostgreSQL again.
2018-10-13
63
SUGGEST
I think this:
“Use a helper function, rather than HTML tags, to build the form, giving it an anonymous function.”
would probably sound better using a collective voice like used in the rest of the book. So, this:
“We use a helper function, rather than HTML tags, to build the form, giving it an anonymous function.”
2018-10-13
I will let the editor make a choice here.
91
79
ERROR
Trying to update the users before the password with the iex command at the bottom of the page. It looks like:
iex(1)> alias Rumbl.Repo
Rumbl.Repo
iex(2)> alias Rumbl.Accounts.User
Rumbl.Accounts.User
iex(3)> for u <- Repo.preload(Repo.all(User), :credential) do
…(3)> Repo.update!(User.registration_changeset(u, %{
…(3)> credential: %{email: “#{u.username}@example.com”,
…(3)> password: “temppass”}
…(3)> }))
…(3)> end
[debug] QUERY OK source=“users” db=3.5ms decode=7.6ms
SELECT u0.“id”, u0.“name”, u0.“username”, u0.“inserted_at”, u0.“updated_at” FROM “users” AS u0 []
[debug] QUERY OK source=“credentials” db=3.7ms queue=0.1ms
SELECT c0.“id”, c0.“email”, c0.“password_hash”, c0.“user_id”, c0.“inserted_at”, c0.“updated_at”, c0.“user_id” FROM “credentials” AS c0 WHERE (c0.“user_id” = ANY ($1)) [[6, 5, 4, 3, 2, 1]]
(RuntimeError) you are attempting to change relation :credential of
Rumbl.Accounts.User but the `:on_replace` option of
this relation is set to `:raise`.
By default it is not possible to replace or delete embeds and
associations during `cast`. Therefore Ecto requires all existing
data to be given on update. Failing to do so results in this
error message.
If you want to replace data or automatically delete any data
not sent to `cast`, please set the appropriate `:on_replace`
option when defining the relation. The docs for `Ecto.Changeset`
covers the supported options in the “Related data” section.
However, if you don’t want to allow data to be replaced or
deleted, only updated, make sure that:
* If you are attempting to update an existing entry, you
are including the entry primary key (ID) in the data.
* If you have a relationship with many children, at least
the same N children must be given on update.
status
The response codes aren’t quite accurate. Specifically 400 and 500 series codes. They are both error codes but 400-499 are bad client requests. 500-599 are bad server requests.
2018-10-13
79
ERROR
If, like me, you didn’t actually type in all the code trying out ``changeset`` and testing the validity, but instead went directly to the bit about updating existing users…
You’ll need “alias Rumbl.Accounts.User”, either before or after `alias Rumbl.Repo` for the remaining code to work.
2018-10-13
72
ERROR
Later in the book, I had issues about it not finding the ``Comeonin.Bcrypt.dummy_checkpw()` method. I had to add another dependency:
`{:bcrypt_elixir, “~> 1.0”}`
2018-10-13
93
ERROR
authenticate_by_email_and_pass calls:
Comeonin.Bcrypt.dummy_checkpw()
which should be:
Comeonin.Pbkdf2.dummy_checkpw()
2018-10-13
171
SUGGEST
“Let’s ease up the number of hashing rounds to speed up our test suite by adding these configuration lines to config/test.exs:”
Is probably better as:
“Let’s ease up the number of hashing rounds to speed up our test suite by adding this configuration line to config/test.exs:”
Now that there is only one line added.
2018-10-13
94
SUGGEST
The paragraph following the session/new.hmtl.eex code listing states…
“We use form_for as in our new-user forms, but instead of passing a changeset, we pass the %Plug.Conn{} struct.”
However, it’s not clear from the code listing how the empty struct is being passed. Can this be clarified?
2018-10-13
50
SUGGEST
At the end of page 49 it explains about RumblWeb.UserView.render and the end of page 50 it explains about Phoenix.View.render, with paragraphs on rendering error message in between.
I find it easier to get the context of behaviour if the explanation of Phoenix.View.render follows RumbleWeb.UserView.render directory, and move the error rendering paragraph to the bottom.
2018-10-13
Interesting suggestion. I have read it a couple of times through and think I like it as is for now. Thought provoking idea though.
39
ERROR
The PDF shows:
children = [
# Start the Ecto repository
Rumbl.Repo,
# Start the endpoint when the application starts
RumblWeb.Endpoint,
# Starts a worker by calling: Rumbl.Worker.start_link(arg)
# {Rumbl.Worker, arg},
]
Whereas the actual code generated is:
children = [
# Start the Ecto repository
supervisor(Rumbl.Repo, []),
# Start the endpoint when the application starts
supervisor(RumblWeb.Endpoint, []),
# Start your own worker by calling: Rumbl.Worker.start_link(arg1, arg2, arg3)
# worker(Rumbl.Worker, [arg1, arg2, arg3]),
]
Since the book is still in beta, when released it should correspond to whatever is the latest versions of software at that time.
2019-01-19
39
SUGGEST
The last paragraph on page 39 and first paragraph on page 40 talk about the application’s supervision tree. This piece felt out of place in this section and was a distraction. I would suggest moving this somewhere else or just deleting.
2019-03-15
40
TYPO
The first code sample on page 40 lists the path to the file as: controllers_views_templates/listings/rumbl/lib/rumbl/accounts/user.ex. However, the correct path is: rumbl/lib/rumbl/accounts/user.ex
2019-01-19
94
TYPO
Actually this is more a question.
For some reason in RumblWeb.SessionView it needs an extra empty line after use statement to work for me:
defmodule RumblWeb.SessionView do
use RumblWeb, :view
end
If I don’t have the extra line as the book showed, I got RumblWeb.SessionView module not available.
Is this a bug in Phoenix itself?
2019-01-21
We can't reproduce this error. Did you try the phoenix slack channel or mailing lists?
94
OK
In the code snippet of “/templates/session/new.html.eex”
I think you forgot to include the flash message notification. You just wrote two input fields one for email and other for password. If something went wrong user can’t see any flash notification!
2019-01-22
We are getting flash messages per CM. Hope this build resolves your problem. The flash notice is in the template.
93
ERROR
Function “authenticate_by_email_and_pass(email, given_pass)”, it used in the cond-do block code, in the third cond,
true ->
Comeonin.Bcrypt.dummy_checkpw()
{:error, :not_found}
this produces error when you try to submit wrong login, it report that this Module, “Comeonin.Bcrypt” is not available. I think we need to include in mix.exs -> deps, the bcrypt algorithm package, like this:
{:comeonin, “~> 4.1”},
{:pbkdf2_elixir, “~> 0.12”},
{:bcrypt_elixir, “~> 0.12”} <<<<<<
After I did that, no more errors.
Thanks!
2019-01-21
na
na
SUGGEST
I am trying to use Phoenix to create a REST server which will have a few nested APIs. I find no documentation in the book at all on how to deal with nested resources. There is documentation for nested resources in the online Ecto documentation, but none of that of course helps with what I need to do in Phoenix specific entities, e.g. contexts, controllers, views, etc. Shouldn’t this be documented???
2019-01-19
We're not going to get to this kind of change in this book.
527
ERROR
Code figures are incorrect and not same as downloaded code.
Call to compute_additional_info is passed wrong var name:
Task.start_link(fn -> compute_additional_info(ann, socket) end)
Should be “annotation” not “ann”
The function broadcast_annotation(socket, annotation) function should be broadcast_annotation(socket, user, annotation)
2019-01-23
71
DEFER
The registration chapter seems a bit naive, in that no verification of the email address is performed. Adding this to the example might also show off some other interesting aspects of Phoenix.
2019-01-22
We thought about it but found it difficult to walk the line between writing a nontrivial app and providing too much data for 300 page book. Longer books of this type are just too much to manage.
19
OK
With Ubuntu 18 and Erlang 21.1 and Elixir 1.7.3 calling mix phx.server on new project fails with a missing cowboy plug error. It also fails with Erlang 20 and Elixir 1.6.6 - same error.
The default created phoenix project create with mix phx.new hello, the mix.exs file needs {:plug_cowboy, “~> 1.0”} in order to compile (or the new project does not compile with a missing cowboy plug error).
If you try with cowboy 1 then use above, with cowboy 2 then use 2.0 above.
2019-01-23
we have not been able to reproduce this problem.
173
SUGGEST
In the end of the ‘Testing Views and Templates’ section, there is this sentence: “Let’s move on to contexts.”. But contexts were treated before - this is the last section before the wrap up. I believe this sentence should be removed.
> In that function, we build a video struct with the video ID.
I think this meant to say “we build an annotation struct”, as per the code.
2019-01-21
219
211
OK
The annotate_video/3 function takes a User struct and a video_id as its first two args. Going back to this snippet, I’m wondering why accept an ID for the one association and why a struct for the other. Presumably it has to do with piping to the put_user/2 function, but it would be nice to know why.
2019-01-21
user_id isn't enough, but video_id is. We need the full user for put_user but we don't need the full video. I am not changing the book because answering this question inline adds a surprising amount of clutter.
\n
\nNice question though!
77
OK
defmodule Rumbl.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias Rumbl.Accounts.Credential
schema “users” do
field :name, :string
field :username, :string
has_one :credential, Credential
timestamps()
end
def changeset(user, attrs) do
user
|> cast(attrs, [:name, :username])
|> validate_required([:name, :username])
|> validate_length(:username, min: 1, max: 20)
end
def registration_changeset(user, params) do
user
|> changeset(params)
|> cast_assoc(:credential, with: &Credential.changeset/2, required: true)
end
end
defmodule Rumbl.Accounts.Credential do
use Ecto.Schema
import Ecto.Changeset
schema “credentials” do
field :email, :string
field :password_hash, :string
belongs_to :user, Rumbl.Accounts.User
defp put_pass_hash(changeset) do
case changeset do
Ecto.Changeset{valid?: true, changes:{password: pass}} ->
put_change(changeset, :password_hash, Comeonin.Pbkdf2.hashpwsalt(pass))
_ ->
changeset
end
end
end
…(14)> (ArgumentError) unknown field `password`. Only fields, embeds and associations (except :through ones) are supported in changesets
(ecto) lib/ecto/changeset.ex:541: Ecto.Changeset.type!/2
(ecto) lib/ecto/changeset.ex:516: Ecto.Changeset.process_param/7
(elixir) lib/enum.ex:1925: Enum.“reduce/3-lists^foldl/2-0”/3
(ecto) lib/ecto/changeset.ex:501: Ecto.Changeset.cast/6
(rumbl) lib/rumbl/accounts/credential.ex:17: Rumbl.Accounts.Credential.changeset/2
(ecto) lib/ecto/changeset/relation.ex:113: Ecto.Changeset.Relation.do_cast/5
(ecto) lib/ecto/changeset/relation.ex:297: Ecto.Changeset.Relation.single_change/5
(ecto) lib/ecto/changeset/relation.ex:105: Ecto.Changeset.Relation.cast/4
(ecto) lib/ecto/changeset.ex:746: Ecto.Changeset.cast_relation/4
2019-01-21
Need more context; where in the book; etc.
19
TYPO
This is somewhere between a typo and a suggestion.
On page 19, you write:
> Let’s use a task now to create our first Phoenix project, like this:
> $ mix phx.new hello
> …
Then you say:
> We’re all set! Run your Phoenix application:
> \t$ cd hello
> \t$ mix ecto.create
> \t$ mix phx.server
We’ll call the above SECTION A.
After SECTION A, you explain about database errors, and say you can also run the server inside iex. Then you explain that phx.new created a new project.
And then, after all that, you have what we’ll call SECTION B:
> At the bottom of the mix phx.new output, you can see a few sentences that tell you what to do
> next. We’ll skip the instructions related to ecto, since our application won’t use a database
> for now. We want to start Phoenix, though. Change into the hello directory and run the
> Phoenix web server through Mix, which will start looking for requests on port 4000, like
> this:
>
> $ cd hello
>
> hello $ mix phx.server
> …
Clearly, SECTION B is just a more verbose version of SECTION A. I would assume one was written, then the other, and someone forgot to remove the first version.
I think this could be fairly confusing for brand new users, so I thought I would point it out.
2019-01-19
127
115
ERROR
When editing a video, edit/2 raises an error:
(RuntimeError) attempting to cast or change association `user` from `Rumbl.Multimedia.Video` that was not loaded. Please preload your associations before manipulating them through changesets
I solved it with Repo.preload
2019-06-08
27
ERROR
In the file structure figure right under “Elixir Configuration”, “application.ex” is found under “lib/” where as it seems to be under “lib/hello/” for me.
Might be worth validating.
2019-01-19
44
SUGGEST
Book has: “undefined function: RumblWeb.UserController.init/1
(module RumblWeb.UserController is not available)”
RC2 returns: “function RumblWeb.UserController.init/1 is undefined (module RumblWeb.UserController is not available)”
Needs updating.
2019-01-19
58
SUGGEST
This bug still exists in 5.0. The code sample does not include this line: “alias Rumbl.Accounts.User” and the user may think they are required to change the alias, not simply add “alias Rumbl.Repo”. Testing against rc2.
2019-01-19
161
OK
The whole passage is kind of confusing, as there is this example code but no source file etc mentioned.
“Preparing for Logged-In Users
You might be tempted to place the user_id in the session for the Auth plug to pick up, like this:
conn()
|> fetch_session()
|> put_session(:user_id, user.id)
|> get(”/videos“)
This approach is a little messy because it assumes an implementation. We don’t want to store anything directly in the session, because we don’t want to leak implementation details. Alternatively, we could do a direct request….”
Where should this “tempting” code go? into the test?
Also: Where dont want to leak implementation details out to? Are we assuming an implementation inside the test and its messy because of this?
2019-01-21
62
SUGGEST
Building Resource Routes: perhaps a reminder to bounce the server after changing the router.ex file.
2019-01-19
36
TYPO
“A request enters through the endpoint (lib/rumbl_web/endpoint.ex) and then goes into the router (web/router.ex).” should probably read “A request enters through the endpoint (lib/rumbl_web/endpoint.ex) and then goes into the router (lib/rumbl_web/router.ex).”
2019-01-19
31
TYPO
Nit picking here anyway and I am not sure if it’s a typo but it seems like there is one too many “only” in the following “This stack only calls the function that accepts only JSON requests, …”.
Did you mean “This stack only calls the function that accepts JSON requests, …”?
2019-01-19
80
TYPO
In Creating Users, the document says, “At this point we have a couple options.” This is slangly. The correct expression is “At this point we have a couple OF options.” and this is even more slangly. :)
2019-01-19
233
ERROR
When changing the supervision tree and restart strategy back to the original, (on the code section named ‘opt/rumbl/lib/rumbl/application.ex’, a ‘Rumbl.InfoSys.Supervisor’ module is inserted on the children list, but this module doesn’t exist. The original children list has only ‘Rumbl.Repo’ and ‘Rumbl.Endpoint’.
2019-01-23
192
DEFER
The solution provided for generating SEO friendly URLs in the book is really clean, however, it just extracts the ID from the slug. One might also need to check if the provided url matches the actual video slug.
Accessing both urls will result in playing the video, which does not seem right. I am curious how you would go around this and will be happy to see your solution in one of the following editions.
2019-01-22
253
ERROR
On the `otp/listings/rumbl/lib/rumbl_web/channels/video_channel.change1.ex` block of code at the end of the page, the new `compute_additional_info` function is called with `ann` as first argument, but `ann` is undefined on this context. It should be `annotation` as matched on line 3.
2019-01-21
254
ERROR
The `broadcast_annotation` should take a third argument for the user being rendered (passed to the UserView on line 16 of the first block of code).
Both the function definition and the two calls to it should be fixed.
2019-01-23
254
ERROR
On the second block of code on this page, there is call to `Accounts.get_user!` passing the `result.backend.name()` parameter, but the `get_user!` function expects an `id` instead of the username.
`Accounts.get_by(username: result.backend.name())` could be used instead
2019-01-23
3
TYPO
“The router compiles down to the cat-quick pattern matching.”
I’m not sure if “cat-quick” is a typo or a term I’m unfamiliar with, but some googling didn’t turn up anything, so I’m guessing it’s a typo. If it’s not, it’s an unusual enough term that a definition would be helpful.
2019-01-19
93
ERROR
Function “authenticate_by_email_and_pass(email, given_pass)”
uses Comeonin.Bcrypt.dummy_checkpw(), but Pbkdf2 is used in the rest of the example, should be changed to Comeonin.Pbkdf2.dummy_checkpw() (otherwise the Bcrypt must be included in the mix file and the 2 algorithms would have different timings, so the dummy-check would be useless).
2019-01-21
253
245
SUGGEST
> This file is ignored from version control so you can include sensitive credentials properly.
Depending on book audience, it might be worth clarifying that this is thanks to the generator creating a .gitignore file.
2019-01-21
18
ERROR
The instructions for installing Phoenix need to be updated since the archives repository is no longer in use.
The command:
$ mix archive.install https: //github.com/phoenixframework/archives/raw/
master/1.4-dev/phx_new.ez
should be replaced with:
$ mix archive.install hex phx_new
2019-01-19
82
ERROR
There is no (obvious?) explanation of changing the new action to use the registration_changeset. If the action still uses the regular User.changeset, then there is an error rendering the form.
2019-01-21
117
TYPO
s/properly lockdown access/properly lock down access/
2019-01-21
126
SUGGEST
“Use what you’ve learned to associate videos and categories in our application. In older versions of Phoenix, most developers put complex interactions in controllers. As it has evolved, we place such concepts in contexts to leave controllers as thin and simple as possible. These interactions now live in our context layer. We’ll put query functions in our schema layer.”
You could probably strike this whole paragraph. The first sentence is a little misleading, as it is an imperative that made me think for a moment that I was supposed to do so as “an exercise left to the reader”. The remainder of the paragraph is simply a topic that has already been mentioned so many times up to this point that it doesn’t really add anything here. Simply moving on to the following paragraph is sufficient.
2019-01-21
129
SUGGEST
“Remember, the ^ operator (called the pin operator) means we want to keep ^username the same.”
Unless I’ve missed something, this is the first time in this book that the pin operator has been mentioned despite it having been used in several places prior to this. That may be fine, since I think this book assumes at least some familiarity with Elixir going in. However, this sentence reads as though the pin operator has already been discussed in this book.
2019-01-21
154
ERROR
Broken link to Ecto.Adapters.SQL.Sandbox in the footnote.
2019-01-21
170
TYPO
s/and finally make that no user_id is in the session/and finally make sure that no user_id is in the session/
2019-01-21
31
SUGGEST
There is an empty note box at the top of this page. At the end of the previous page, there’s a “José says” box, and I wonder if it mistakenly bled onto page 35.
2019-01-19
Issues like these will be fixed when the book goes to typesetting.
19
SUGGEST
The output of the mix phx.new hello command is formatted like the text of the book, making the section extremely confusing. The output of the command, posing as book text, instructs the reader to set up their database, but the actual text of the book, lower, instructs the user not to set up their database.
2019-01-23
34
OK
Is the second function in the pipeline supposed to say “browser?” I think it would make more sense to say “router” in the same way this general pipeline has been laid out before. I’m unsure how any browser fits in here in the request lifecycle.
2019-01-22
The browser() is the pipeline from the router.
48
TYPO
More of an inconsistency, but during the refactoring of the user display code to a new file, the code switches from using “” tags to “” tags.
2019-01-19
I don't think we're going to catch all of this up.
40
ERROR
The following iex session on p.40 did not work for me:
I think my earlier errata had to do with a spelling mistake Rumble v. Rumbl.
2019-01-19
43
SUGGEST
The error:
key :show not found in: [index: []]
is caused by specifying:
Routes.user_path(@conn, :show, user.id)
in the link() function in templates/user/index.html, AND you have not defined a route in router.ex that goes to a :show action. It does NOT matter whether a :show action has been defined in the UserController. Only the route is needed to get rid of that error.
2019-01-23
45
OK
The error:
key :show not found in: [index: []]
is caused by specifying:
Routes.user_path(@conn, :show, user.id)
in the link() function in templates/user/index.html, AND you have not defined a route in router.ex that goes to a :show action. It does NOT matter whether a :show action has been defined in the UserController. Only the route is needed to get rid of that error.
2019-01-23
we can't reproduce this problem
51
OK
The book says:
——
In particular, each template receives a couple of special assigns when rendering, namely view_module and view_template…:
Okay, but where does the actual assigns variable come from, i.e the 3rd argument to render()??
2019-01-19
37
SUGGEST
I started over and renamed my project Rum because I had too many mistakes typing Rumble instead of Rumbl. When I say “Rumbl” in my mind, my fingers type “Rumble”.
2019-01-19
Sorry... that's the only url we could find that was short and cheap.
233
TYPO
In the testing section section, in the media.pragprog.com/titles/phoenix14/code/testing_mvc/listings/rumbl/test/rumbl/accounts/accounts_test.exs file, it says “describe register_user/2” but Accounts.register_user has an arity of 1
2019-01-21
40
TYPO
username spelled incorrectly.
iex> user = %{usernmae: “jose”}
2019-01-19
106
SUGGEST
Second paragraph under the router.change1.ex code block:
I suggest changing the sentence:
Furthermore, because pipelines are also plugs, nothing is stopping us from giving a plug, like authenticate_user, to pipe_through.
To something like:
Furthermore, because pipelines are also plugs, nothing is stopping us from passing a plug, like authenticate_user, to the function pipe_through.
Something more explicit. So far the book is great.
2019-01-21
111
SUGGEST
“If you’re a careful reader…” I am not sure where this paragraph is going. It looks like you are going to discuss two way navigation and lazy loading, but ends up making vague comments about operations support.
2019-01-21
77
SUGGEST
If the reader’s not working on a new console, they’ll need to run `“r Rumbl.Accounts.User`” to manually reload the module in order to successfully call the newly added function` “registration_changeset/2`” in the code example. It might be worth explicitly mentioning this and also showcase the nifty module reloading functionality in iex!
2019-01-21
74
TYPO
potentially misplaced parenthesis in code sample. null is not an option on references() and doesn’t affect the SQL output
hxxps://hexdocs.pm/ecto/2.0.2/Ecto.Migration.html#references/2
This statement “if you had the brilliant idea of converting the whole API site to accept only XML” sounds sarcastic due to the usage of the word “brilliant”.
I would suggest that the book should avoid sarcasm to create a welcoming atmosphere for learning, and to show the Elixir community as friendly.
A better way to phrase the same idea would be: “if you had the need to convert the whole API site to accept only XML”.
2019-01-19
254
ERROR
In the compute_additional_info(annotation, socket) function, Accounts.get_user!(result.backend.name()) is used. But Accounts.get_user! function needs id, not username. It should be Accounts.get_user_by(result.backend.name()).
2019-01-23
154
TYPO
“Let’s tests…” => “Let’s test…”
2019-01-21
160
OK
Video controller wasn’t locked behind user authentication since requests are only piped through authenticate_user plug when scoped under “/manage” and Routes.video_path(:some_action) doesn’t resolve into a path with scoping as is.
2019-01-22
We only scope video editing to /manage since the /watch urls are made to be public.
160
SUGGEST
re: #84180
Looks like the issue comes from adding an additional videos resources scoped under “/manage” instead of replacing the original videos resources scoped under “/” with one under “/manage” in the router file. (see page 103 and 106)
I’d suggest making it a bit more explicit that it’s meant to be a replacement rather than an addition otherwise it’s easy for that vestigial line to stick around and cause trouble down the line.
2019-01-22
162
TYPO
assert html_response(conn, 200) =~ ~r/Listing videos/
“videos” in the regex need to be capitalized into “Videos” for assertion to pass and match what gets autogenerated by the phoenix mix task
2019-01-21
169
TYPO
Duplicated test “logout drops the session”, looks like the first occurrence was not supposed to be included
2019-01-21
140
TYPO
1/3 of the way down the page there is a two-sentence paragraph with a typo in the second sentence:
“We updated our video with a category that exists. The update works, but suppose tried to update a video with a bad category:”
Typo: “…but suppose tried…”
Correction: “…but suppose we tried…”
2019-01-21
74
ERROR
In the last paragraph on the page that starts with “Deleting a user should also delete the associated credentials”, the second to last sentence says: “we shouldn’t allow credentials without users, so we also passed null: false”.
For the code sample above the paragraph (create_credentials.change1.exs), that sentence makes it seem like :user_id should also have a null: false param passed to add. The code and sentence seem conflicting, so just wasn’t sure if it was an error or not.
Thanks!
2019-01-19
92
OK
I think :not_found should be :notfound in the bottom most code example on page 92
2019-01-21
116
TYPO
After creating the action function, I think you also want to tweak the params of the edit method to also be passed current user, along with the new and create method in the last code example on that page. This change to edit is shown on 117, but not explicitly stated.
2019-01-21
200
SUGGEST
To continue the breakdown earlier of “topic:subtopic”, I’d consider rewording the following:
“They’ll be able to join any number of channels and any number of topics on a channel.”
into
“They’ll be able to join any number of channels and any number of subtopics on a channel.”
Even better would be to use videos as an example. Something to the effect of clients can join multiple channels such as the videos channel and multiple subtopics such as multiple individual videos.
2019-01-21
Good comment but I think we want to leave the terminology alone here.
154
TYPO
It seems like the :not_found constant used in the book has been replaced with :notfound?
This :not_found I think is the one introduced in our explicit error message.
53
40
ERROR
iex> user = %{usernmae: “jose”}
should be
iex> user = %User{usernmae: “jose”}
2019-01-19
intentional misspelling to demonstrate struct
220
TYPO
“Next, we modify our call to Multimedia.list_annotations by passing our last_seend_id on line 8.”
last_seend_id => last_send_id
2019-01-21
1
TYPO
Incomplete sentence: “We know that Phoenix is a bold name for a bold framework, but look.”
2019-01-19
we'll let the editors take this one. I think it reads fine.
16
DEFER
When you say “Ecto allows us to organize our code in this way. It separates the code with side effects, which changes the world around us, from the code that’s only transforming data.” — you really need to take a knee and spend a few minutes talking about your notion of “side effects”. I’ve heard this in the Elixir forums too, and as far as my experience, this notion of “side effects” is not a universally understood definition. What do you mean exactly? Why is a database operation a “side effect” but a “transformation” not? I think this paragraph really loses people.
2019-01-22
We'll look at this one. Good comment.
23
SUGGEST
One of the endless points of confusion with Elixir (and Ruby for that matter) is knowing when the fat arrow (=>) should be used in place of the colon (:). This is the first time we see the fat arrow notation — you should spend a quick moment to explain why we use it here instead of the colon notation.
2019-01-19
40
OK
You really need to explain more of your reasoning here with respect to contexts. “Contexts” is easily the most confusing part of Phoenix 1.4 and I think it’s honestly just because the explanations have been so lacking. Other languages/frameworks introduce “service classes” that serve much of the same purpose: i.e. isolating/abstracting bits of functionality to separate modules/classes. Contexts are not that different. But you can’t just jam them into the book like this (or indeed, into the framework) and expect anyone (even seasoned developers) to know what you’re doing. This section jumps from users to accounts and back again with a million alternative ways of doing things that are left completely un-explained.
If nothing else, mention “service classes” and the fact that this is nothing more than an organizational strategy and a way to deal with the single-responsibility-principle, because really, the organization into an “Accounts” context is entirely arbitrary and if a dozen other devs tackled this same problem, you’d undoubtedly end up with a dozen different equally valid solutions.
2019-01-23
51
SUGGEST
“This allows you to render the view and template for your controller action in the layout with a plain render function call. No magic is happening here.”
This is frustrating because you don’t include an example. No magic?!? Really? You have not shown us what’s behind the curtain enough to make a claim like that. There’s another issue I’m filing about this, but it’s not at all clear from the code or text (i.e. it is black magic) as to how Phoenix renders views… there’s no clear example presented that shows why views are modules (why?!?) and templates are functions (why?!? this is so arbitrary), so without a clear in-your-face example, the claim that this is so un-magical is ludicrous. You could definitely save some friction by showing (not telling) how Phoenix renders the view.
2019-01-19
We'll see what comments come in from technical reviewers. From over 500 comments so far we need to be judicious about the ones we address.
55
OK
When you include the sample schema code for users with “field :name, :string” etc, it would be really nice to include a link to the list of all supported data types and options. We can guess stuff like “:string” and maybe “:integer”, but holy smokes, Ecto in particular is so sparse with its examples — why starve the reader with these critical bits of info? Throw us a link! Broadcast the options loudly! This is the place to demonstrate and teach what is possible.
2019-01-19
69
SUGGEST
The code sample that includes “create table(:users) do” should have an aside as to why you use atom notation (i.e. :users) instead of a string (i.e. “users”). Really, both alternatives work, but it’s one of those bits of uncertainty that cripples newcomers and that experienced Elixir devs never think about. Help the newcomers out! Just mention a brief explanation here and you will avoid that headache!
2019-01-19
72
OK
“By now, you should be seeing the value of the context API.”
This is sort of a throw-away statement… show, don’t tell. Can you explain and/or clarify why this context API is valuable? I’m not sold on it. I would have structured my code to have one context per resource, period… why all this self-congratulatory praise about being valuable? What exactly about this approach is good or useful and can you state that with an example or an explanation that doesn’t leave readers raising an eyebrow?
2019-01-19
72
SUGGEST
“With our repo calls in place, we’re ready to try it out even though we haven’t touched our controller code at all.”
Remember: you should remind readers that they have to restart Phoenix… some of those changes don’t register right away.
2019-01-19
74
OK
“In the past versions of Phoenix, you’d probably just use the Accounts.User.changeset.”
This is unclear… we’re using that function in our code in THIS version of Phoenix. What are you talking about? Are you suggesting that we should put some code in the context module instead of in the changeset function? If so, clarify that and explain your reasoning a bit more.
2019-01-19
102
DEFER
With the code sample of:
plug :authenticate when action in [:index, :show]
Why are we only authenticating for 2 of the possible actions? Is that a security hole? What happens if malformed or unauthorized data is submitted to one of the other endpoints, e.g. :update?
2019-01-22
103
OK
“Let’s add a tiny function to RumblWeb.Auth that receives the connection and the user, and stores the user ID in the session:”
Why are you adding this new “tiny” function into a module that has been tapped as a plug? Isn’t this breaking the single responsibility principle for a module and making it take on multiple responsibilities? Couldn’t/shouldn’t these other functions be in their own isolated module? I think you should at least explain your decision to include this function here.
2019-01-25
Thanks for your comment.
106
TYPO
“Next, lets write the function that does the actual work.”
Should be “let’s” — it’s a contraction of “let us”.
2019-01-21
106
OK
The “authenticate_by_email_and_pass” function includes a “cond do” block — the default value of that is a “true” value — it would be nice to reinforce how those blocks work. Remember: this is an educational book and it should reinforce/repeat stuff that readers may have learned (or missed) from any generic Elixir info.
2019-01-21
115
OK
The introduction of the “mix phx.gen.html” command needs some introduction. It’s brutally long. And if you aren’t completely clear on the reasoning/necessity of the context module, its arguments become even more baffling and onerous. I don’t know of any other framework that attempts to leverage such long-winded command-line arguments, so at a minimum, it would be nice to at least acknowledge that this is a long command.
2019-01-21
I am having a hard time separating the comments about the book from comments about the framework. Going to wait on this one.
116
OK
When we move the “authenticate” function from the user_controller to the RumbleWeb.Auth module, we change the name to “authenticate_user”… but it seems needlessly confusing. Why not just name it “authenticate_user” from the get-go? There’s already a lot going on here with moving a function between modules and changing its visibility from defp to def.
2019-01-21
117
OK
“First, let’s share authenticate_user/2 across all controllers and routers.” — this is a key place to make mention of “arity” and function signatures… it’s a bit of a surprise that Elixir allows for multiple function defs of the same name. Remind the readers of this amazing feature! In the code sample too, you should mention that the import statement requires the arity to know which functions to import (this is very unlike languages like Python or Go):
import RumblWeb.Auth only: [authenticate_user: 2]
2019-01-21
130
OK
There is a lot of discussion in this section about “side effects”. I think you should explain why you view certain actions as “side effects”. I think many developers may think of a database change or reading data from a socket as the “main event.”
2019-01-21
131
OK
There are not enough examples in the Ecto docs to just name drop a bunch of operators and functions and expect anyone to magically know how to use them. My observations of developers using Phoenix is that Ecto is hands-down the single most frustrating and confusing obstacle that comes up, and I believe it’s due almost entirely to a scarcity of examples in its docs… there has to be enough examples in variations to make it clear what a particular option/function does. If you don’t take every opportunity in an educational book to stay ahead of those roadblocks, you are doing the readers (and Elixir + Phoenix) a disservice.
2019-01-21
this comment isn't actionable.
132
SUGGEST
Why are you using the pin operator in front of a string — it’s not even a variable:
where: ilike(u.username, ^“j%”)
Others have pointed out that the pin operator was never introduced in the book, and this usage goes beyond my understanding of it. I’m assuming there will be other readers left scratching their heads at this.
2019-01-21
132
OK
Consider omitting “fantastic” in the sentence beginning with “Now, let’s say that we want to take advantage of this fantastic count feature”. It comes across as a bit snarky (same with the wink to usernames starting with j), especially when Ecto is so frustrating and it’s not at all clear what rules apply when queries get sliced up. Again, some more thorough examples in Ecto would help users understand how the same query could be represented in multiple variations, including as a series of fragments.
2019-01-21
133
OK
When you say “we could use a longer list with more bindings if our query had joins.” I think you should show, not tell. It’s worse when you know that a tool CAN do what you want, but nobody tells you HOW to do it.
2019-01-21
133
OK
It seems overly dramatic to say “you don’t have to panic and fork Ecto to build your own mapping layer” — forking?!? We barely understand Ecto purpose and very little of what it can do, so any mention of forking it seems absurd.
I know I have harped on this, but more than anything else, Ecto needs examples. I would even consider restructuring this chapter to start with raw database queries (the kind you could execute in your DB client) and then working backwards towards more idiomatic representations of them using fragments and finally the Ecto operators etc.
After committing seppuku on myself trying to adapt working database queries into ActiveRecord and other ORM’s, I think a case really can be made that ORMs are an anti-pattern — they definitely can be an enormous time-suck. With regards to Ecto, it is probably good to error on the side of too many examples and variations so that this database mapping layer is the useful tool it was intended to be.
2019-01-21
maybe you should check out our ecto book. I don't think we could provide all of the detail you're looking for in a single chapter of the Phoenix book.
133
OK
Consider clarifying the sentence that begins “A query fragment sends part of a query directly to the database” — it’s not clear from that sentence whether each fragment executes against the database separately or if fragments are bundled together into a larger query string that may or may not get executed later via some other command.
2019-01-21
141
OK
“Second, you could configure the database references to either cascade the deletions or simply make the videos.category_id columns NULL on delete.”
Consider showing an example here (presumably using the :nilify_all option?). Show, don’t tell. It’s only after the reader has seen a few examples that the long-form documentation of options etc. become useful.
2019-01-21
145
SUGGEST
In the paragraph that begins with “You can probably already tell that the decisions made throughout the Phoenix platform make testing a joy.” it comes across as overly subjective and self-congratulatory. Consider toning it down. The intro to the book did this really well, where you stated what goals you tried to achieve with Phoenix or Elixir and we (the readers) could see how it stacked up against some stiff competition. That intro had a much better vibe.
2019-01-21
150
OK
Use a colon to emphasize the statement that follows it. These 2 sentences
“Libraries are like macros. Don’t use one when a simple function will do the job.”
should instead be represented as a single sentence with 2 clauses separated by a colon:
“Libraries are like macros: don’t use one when a simple function will do the job.”
2019-01-21
I like the way it reads but we'll let the editors make a call here.
152
ERROR
In the test labeled “requires password to be at least 6 chars long”, the following assertion:
assert %{password: [“should be at least 6 character(s)”]} …
must instead reference a nested structure:
assert %{credential: %{password: [“should be at least 6 character(s)”]}} …
2019-01-23
153
SUGGEST
The test labeled “returns user with correct password” introduces for the first time the use of a second argument to the test macro:
test “returns user with correct password”, %{user: %User{id: id}} do
I have never seen this before, and I even poured over the ExUnit docs trying to spot where this is documented… I didn’t find it. Major “wow” / “WTF” moment there. You should really take the time to explain what that 2nd argument is… is it output of the setup? Or something else?
2019-01-21
it's the test context. We can't be a resource for all elixir; going to leave that as is.
157
SUGGEST
This section ends rather abruptly: “As expected, they are all green.” The section is titled “Using Ecto.Sandbox for Test Isolation and Concurrency” — but where was the talk about concurrency? Where are there demos/examples/explanations of different approaches? I felt like this section ended without accomplishing its mission.
2019-01-21
159
OK
With the sentence reading “Then setup places a base conn into our test metadata and returns a new context with this connection, which flows into our page_controller_test as an optional second argument to the test macro.”
I really could not follow this…. I would not guess that the code under discussion had anything to do with arguments to the test macro. It really felt like black magic. I mentioned the magical 2nd argument to the test macro separately: this is its counterpart and I think there’s a great opportunity to up everyone’s testing game by connecting these dots.
2019-01-21
159
OK
“Keep in mind RumblWeb.ConnCase is just a foundation. You can personalize it to your own application as needed.”
Suggesting customization without an example isn’t very useful and makes for a weak conclusion to this section. Consider refactoring the transition to the next section.
2019-01-21
161
OK
“This approach is a little messy because it assumes an implementation. We don’t want to store anything directly in the session…”
Consider elaborating on this, especially what exactly you mean by an “implementation”. What exactly can the tests expect to be stored in the session? Or was the point that the conn should have the user details regardless of whether or not the auth was implemented using sessions (and not JWT, for example)?
2019-01-21
162
ERROR
“We add a new test for the /videos route”
should instead reference the route as /manage/videos per previous definition.
2019-01-21
162
OK
This page includes test code that makes the first use of @tag — what is this new sorcery? This would be a great opportunity to explain that feature and how to use it.
2019-01-21
152
TYPO
Missing asserts in “does not accept long usernames” and “requires password to be at least 6 chars long” on the {error, changeset} lines.
2019-01-23
I *think* what you're saying is that the assertion did not access the credential. If so we've fixed it.
162
TYPO
The line conn = get conn, video_path(conn, :index) should use Routes.video_path(conn, :index) I believe. It is correct in the next code sample for that bit
2019-01-21
60
ERROR
In listing user_controller.change1.ex, the User struct either needs to be fully specified (%Accounts.User{}) or the listing needs another alias for User.
2019-01-19
155
OK
In chapter 3. Controllers, Coding Views an example is given how to create a function that parses a user’s first name from the user’s name field. Yet the hardcoded example-data used at that moment in the book only contains name fields with a first name. That makes the first_name function useless and the example confusing.
2019-01-22
158
TYPO
In the code sample
testing_mvc/rumbl/test/support/conn_case.ex
The line:
import Rumbl.TestHelper
will not be here at this point as it is added a few pages later (PDF page 160).
2019-01-22
162
ERROR
In the code sample: testing_mvc/listings/rumbl/lib/rumbl_web/controllers/auth.change1.ex
The user variable assigned on the first line is never used and will become a compiler warning.
2019-01-21
162
ERROR
In the code sample testing_mvc/listings/rumbl/test/rumbl_web/controllers/video_controller_test.change1.exs
This line is included:
@tag login_as: “max”
This is not required for this section, is mentioned as to be added and is included in the next code sample.
2019-01-21
80
ERROR
in Listing: authentication/listings/rumbl/lib/rumbl/accounts/accounts.change1.ex I only added the register_user method. But I also needed to change the change_user method to use registration_changeset in order to work as intended because the localhost:4000/users/new gets its initial changes from Accounts.change_user
2019-03-15
62
ERROR
resources “/users”, UserController, only: [:index, :show, :new, :create] leads to an error. :new and :show have to be the other way around!
resources “/users”, UserController, only: [:index, :new, :show, :create]
2019-06-07
71
ERROR
The line “alias Rumbl.Accounts.User” first referenced on p54 (controllers_views_templates/listings/rumbl/lib/rumbl/accounts/accounts.ex) needs to also be included in the follow-up code shown @ p71-72 (despite existing in the source code @ ecto/listings/rumbl/lib/rumbl/accounts/accounts.change1.ex).
This will prevent the following error message when viewing “localhost:4000/users”:
Protocol.UndefinedError at GET /users
protocol Ecto.Queryable not implemented for User, the given module does not exist. This protocol is implemented for: Atom, BitString, Ecto.Query, Ecto.SubQuery, Tuple
2019-01-19
57
57
ERROR
Tried to add new data via iex as per the instructions, but kept getting…
(CompileError) iex:7: Rumbl.Acounts.User.struct/1 is undefined, cannot expand struct Rumbl.Acounts.User
I think the server needs to be restarted before the Rumbl.Accounts.User changes are picked up - is that right?
2019-01-19
192
TYPO
Third sentence in Wrapping Up section has an unnecessary “and” in it:
“We then and laid some foundation so we can play our videos in YouTube.”
2019-01-21
10
ERROR
-> mix archive.install
on mac book pro gave the error:
(Mix) Cannot create archive without input directory, please pass -i as an option
Used to install:
mix archive.install hex phx_new 1.4.0
2019-01-19
38,72
SUGGEST
Some examples in the book use gettext, for example on page 38 (PDF), but the only explanation for it is “:gettext for internationalization” on page 72 nothing more. Also, I think the topic internationalization and localization deserves a few pages in this book.
2019-01-19
238
TYPO
In Rumbl.Counter.child_spec the MODULE macro is written as Module.
2019-01-21
241
TYPO
The children definition includes Rumbl.InfoSys.Supervisor although that hasn’t been introduced yet.
2019-01-21
52
TYPO
The closing paragraph of Chapter 3 says ‘In the next chapter, we’re going to back the context’. I guess the intended wording was ‘In the next chapter, we are going back to the context’.
2019-01-23
211
TYPO
In the second paragraph is written “we build a video struct”, but in fact it must be “we build an annotation struct”.
2019-01-21
240
TYPO
Last sentence of the first paragraph is missing the word “an”:
“This function simply returns atom of the table name to use for our ETS table.”
“This function simply returns [an] atom of the table name to use for our ETS table.”
2019-01-25
72
TYPO
When adding the :comeonin and :pbkdf2_elixir dependencies to mix.exs, you also included a line for bcrypt_elixir. You should remove that.
2019-03-15
38,72
OK
I have reported this for B5.0 previously and its marked as “Fixed in: B6.0”, but it is not fixed so I report this again.
Some examples in the book use gettext, for example on page 38 (PDF), but the only explanation for it is “:gettext for internationalization” on page 72 nothing more. Also, I think the topic internationalization and localization deserves a few pages in this book.
2019-03-15
Please don't re-open suggestions. Internationalization is beyond the scope of this book.
81
TYPO
In the sentence “Since we want to expose user functionality though
our context, we add the change_registration function.” “though” should be “through”.
2019-03-15
57
TYPO
When inserting the User “Chris” to the database, I believe the username should be: “mccord” instead of “cmccord”
2019-03-15
27
ERROR
Elixir Configuration section
Phoenix 1.4 project menu structure, under the lib folder, doesn’t find an application.ex file.
2019-03-15
39
TYPO
lib/rumbl/application.ex
children = [
supervisor(Rumbl.Repo, []),
supervisor(RumblWeb.Endpoint, []),
]
has changed to a list.
2019-03-15
170
160
TYPO
“…so we can use user_fixture and video_feature…” should be “…so we can use user_fixture and video_fixture…”
2019-03-15
164
154
TYPO
One of the features that line provides is
should be
One of the features that file provides is
2019-03-15
49
SUGGEST
On page 49: “Phoenix uses singular names throughout, avoiding confusing pluralization rules and naming inconsistencies.”
On page 55: “mix ecto.gen.migration create_users” , it is plural, also the migration on the next page (56) uses plural form i.e. users.
I think either the statement on page 49 should be modified or the migration on pages 55,56.
2019-03-15
72
TYPO
Last Comma in following code causes syntax error.
defp deps do
[
…,
{:comeonin, “~> 4.1”},
{:bcrypt_elixir, “~> 1.0”},
{:pbkdf2_elixir, “~> 0.12”},
]
end
Should be
defp deps do
[
…,
{:comeonin, “~> 4.1”},
{:bcrypt_elixir, “~> 1.0”},
{:pbkdf2_elixir, “~> 0.12”}
]
end
2019-03-15
73
ERROR
The listings and code downloads of the book place the accounts.ex file at lib/rumbl/accounts.ex but the generator command given on page 73 is not given. Instead the command generates a second accounts,ex at lib/rumbl/accounts/accounts.ex
If the accounts.ex file is moved into the accounts folder then the warning is given and the resulting output is much closer to the code in the source downloads
2019-07-21
103
SUGGEST
I have trouble determining where the end of the shell output is. For instance, on page 103 I thought the instructions in the shell output (“Remember to update your repository by running migrations”) was instead an instruction by the book’s authors. I can see now in retrospect that the font is different, but that’s the sort of thing I apparently miss on my first read-through.
2019-03-15
23
SUGGEST
In section “Pattern Matching in Function”, explain how to enter the iex shell.
2019-03-15
1
OK
Please include parallel sections for developers only interested in building REST APIs.
2019-03-15
1
OK
In another erratum, I suggested that parallel sections be added for those only interested in building REST API applications. However, I do see how that might be difficult with the current format of the book. So, I have an alternate suggestion. What not written a separate book intended only for API developers? I would probably be fairly short and would bypass everything specific to server rendered web apps. I for one would purchase it immediately. Thanks
2019-03-15
It's really not a book. It's a blog post and there are several of them around. This doesn't fit in our flow.
39
ERROR
In section “Working with Contexts”, there is a code snippet showing the children list in “/lib/rumbl/application”. That code snippet is out-of-date and will be confusing to readers. The snippet shows:
children = [
Start the Ecto repository
supervisor(Rumbl.Repo, []),
Start the endpoint when the application starts
supervisor(RumblWeb.Endpoint, []),
While the actual code is:
children = [
# Start the Ecto repository
Rumbl.Repo,
# Start the endpoint when the application starts
RumblWeb.Endpoint
# Starts a worker by calling: Rumbl.Worker.start_link(arg)
# {Rumbl.Worker, arg},
]
2019-03-15
76
SUGGEST
Increase the minimum and maximum length of password. See OWASP recommendations here:
www.owasp.org/index.php/Authentication_Cheat_Sheet#Password_Length
2019-03-15
This actually turns into a pretty expensive change for us in the book since the code will percolate through the example code for the whole book. Different apps and use cases will have different requirements. These are configurable as we've specified them.
\n
\nI think we have to close this without a code change, but I left a line in prose to point to these guidelines.
79
ERROR
On page 72, pbkdf2_elixir is used as hashing library. But the hash string on page 79 looks like a bcrypt hash, as it starts with $2b$. A pbkdf2 hash should start with something like $pbkdf2-sha512$.
2019-03-15
Now that is one we never would have caught!
81
TYPO
Any view that requires the user credentials will need to use a specific
changeset for registration. Since we want to expose user functionality though
our context, we add the change_registration function.
This should be “through”.
2019-03-15
190
SUGGEST
The first time the issue of “behavior” vs. “behaviour” comes up is on the bottom of page 190 (Section “Extending Schemas with Ecto Types”).
However, the infobox “Behaviour or behavior?” does not appear until page 236, where “behavior” is actually spelled “behaviour” in the text.
I suggest putting the infobox after the first occurrence. I actually made the mistake of writing “@behavior” when typing the listing and only realized the different spelling when I tried to run my code and received a warning.
2019-03-15
28
ERROR
I don’t see any application.ex file in my lib folder
2019-03-15
33
ERROR
The tree diagram on p. 33 should include the file: channels\\user_socket.ex
2019-03-15
74
TYPO
Phoenix let’s us know …
Shouldn’t it be?
Phoenix lets us know …
2019-03-15
75
OK
When reviewing the user changeset, you explain “cast()”, then you jump directly to the “length” validation, omitting the “required” validation.
2019-03-15
The pages don't always line up exactly for me.
\n
\nI am seeing "validates existence and length". Are you seeing something different?
\n
\nMarking this "not a problem"... please reopen if I have missed something.
41
OK
When playing around in the terminal with the map/struct as explained on page 41:
alias Rumbl.Accounts.User
#=> Rumbl.Accounts.User
jose = %User{name: “Jose Valim”}
it raises a compilation error:
(CompileError) iex:2: Rumbl.Accounts.User.struct/1 is undefined, cannot expand struct Rumbl.Accounts.User
"
2019-03-15
41
TYPO
Errautm #84651 is wrong, - I started “iex” without passing the option “-S mix”. My bad, sorry for that.
2019-03-15
No problem! Glad you're tracking along with us in the book, and helping others for any problems you do find.
164
TYPO
3rd paragraph after “Using Ecto.Sandbox for Test Isolation and Concurrency”
>“Let’s tests…”
should be “Let’s test…”
2019-03-15
52
TYPO
“…we’re going to go back the context…”
Seems like it should be:
“…we’re going to go back to the context…”
2019-03-15
80
SUGGEST
On page 80 and 81 it jumps between using view in iex -s mix and displaying error pages and then repeating using view in iex -s mix with the same content.
2019-03-15
83
TYPO
“In the next chapter, we’re going to go back the context” should be “In the next chapter, we’re going to go back TO the context”
2019-03-15
92
SUGGEST
On the steps after:
-r Rumbl.Accounts.User
alias Rumbl.Accounts.User
Its not clear clear on the next commands what is an input and what is an output.
It should be:
changeset = User.changeset(User{username: “eric”},{})
and then be clear that:
Ecto.Changeset{changes:{}, …} is the output.
When I was typing it out, I wasn’t sure and had to mess with a couple times to get it right.
There should be an introduction with coding conventions with what is input and what is output.
2019-03-15
98
ERROR
When running:
mix phx.gen.context Accounts Credentials credentials email:string:unique password_hash:string user_id:references:users
The output at this time should be (if i am not mistaken):
The Rumbl.Accounts context currently has 6 functions and 1 files in its directory.
In the text it says:
The Rumbl.Accounts context currently has 8 functions and 2 files in its directory.
2019-03-15
86
ERROR
I ran the generate context command, but it didn’t warn me about generating code in an existing context. It created the file /rumblr/accounts/accounts.ex (with the same name/module name as the file accounts.ex in the /rumbl directory)
2019-06-08
93
ERROR
The function change_registration is created, but never used. It could be used right below in the register_user function, but the authors inlined the same call that change_registration is doing.
2019-07-21
97
SUGGEST
You invite the reader to visit localhost:4000 and assume they are not logged in.
But they are logged in already because you invited them to do so on page 95.
So, the reader will see the header with the logout link.
You either have to instruct readers how to delete the session, or assume that they see the logout header.
2019-03-15
116
ERROR
A section in this page says “Phoenix frees you from memorizing unnecessary singular and plural conventions by consistently using singular forms in schemas, controllers, and views.”
However this is wrong, because plural is used on schema definitions.
2019-06-08
Added a "in most cases".
94
SUGGEST
You write, “When a user isn’t found, we use comeonin’s dummy_checkpw() function to simulate a password check with variable timing. This hardens our authentication layer against timing attacks, which is crucial to keeping our application secure.”
As far as I can tell, if dummy_checkpw() were not called then the only thing that a timing attack would be able to determine is whether or not a user with the provided email address exists in the DB. But the registration form already makes this information known because a “has already been taken” error will be rendered if an email of an existing user is entered (see unique_constraint(:email) call on page 76).
I feel like this is either a mistake in the book or could use more clarification, especially since this is security related.
Thanks, and the book is great!
2019-07-21
José? What do you think?
116
TYPO
“Then, the list_user_videos and get_user_videos utility functions will scope a request to the videos a user can see.” - actually you defined the “get_user_video!” utility function, not “get_user_videos”.
2019-03-15
266
ERROR
‘npm install’ throws an error ‘npm ERR! Could not install from “../../../deps/phoenix” as it does not contain a package.json file’
it’s resolved by ‘mix deps.get’ for the whole umbrella project first
at the same time, running ‘mix test’ gives me error that ‘(Mix) Could not start application rumbl_web’ because no ‘RumblWeb.Application’ module is found
2019-03-15
189
DEFER
Users are likely to get a slightly different error when trying to click the “Watch” button from the videos-index page after making the changes to render video links using slugs:
[debug] (Ecto.Query.CastError) lib/rumbl/multimedia.ex:124: value `“10-”` in `where` cannot be cast to type :id in query:
The problem is that no data migration was applied when the slug column was added to the videos table, so all extant videos will have incorrect slugified link paths—e.g., “/watch/1-” rather than “/watch/1-hello.” I worked around this problem by manually updating the slug fields for rows in the videos table.
2019-07-21
152
SUGGEST
It’s mentioned here that we could add :nifily_all to the references function. I tried to do that without rolling back (by creating a new migration), and couldn’t find a proper way to do that. It would be nice if the book showed how to do that the right way
2019-06-08
167
TYPO
“we checked our the ability” should be “we checked our ability”
2019-06-07
171
SUGGEST
On the code “user = conn.assigns[:current_user]” the variable “user” is unused. So maybe just check for “conn.assigns[:current_user]”?
2019-06-08
122
SUGGEST
On the top of the page, the text says:
<<Remember to update your repository by running migrations:
$ mix ecto.migrate>>
But the migration should not happen at this time, since after this:
There are some changes done to the generated migration (adding not null to column name and adding unique index on categories.name);
On page 123, the text continues: <<Finally, migrate your database with your two new migrations […]
[info] create table categories
[…]>>
2019-06-07
132
SUGGEST
Hi,
Is the pin operator needed when the value is a literal in the following expression?
< j_users = from u in users_count, where: ilike(u.username, ^“j”)>>
It is the same as:
iex> j_users = from u in users_count, where: ilike(u.username, “j”)
Regards,
Dan
2019-06-07
Not necessary. It's a stylistic choice, such as the optional commas after the last pair in a map or a keyword dict. Should the user decide to change the literal to a variable, it will still work.
137
SUGGEST
About the phrase:
<<Oops. Our application blows up with a constraint error, similar to the one we
saw when creating duplicated categories.>>
There is no earlier code in the book demonstrating creating duplicated categories. The only place where categories are created is in the seeding script, where the creation of a duplicated category is prevented by first reading:
Repo.get_by(Category, name: name) || Repo.insert!(%Category{name: name})
Best regards,
Dan
2019-06-08
140
ERROR
The following code:
<<
iex> changeset = foreign_key_constraint(changeset, :videos, name: :videos_category_id_fkey, message: “still exist”)
>>
fails with:
(CompileError) iex:17: undefined function foreign_key_constraint/3
2019-07-21
76
SUGGEST
The footnote link to OWASP leads to a valid page but the page redirects visitors to a Github URL which I can’t add here due to anti-spam rules.
2019-06-07
13
TYPO
“We will add a treatment of LiveVeiw in the last chapter.”
Excerpt From: Chris McCord, Bruce Tate, José Valim. “Programming Phoenix ≥ 1.4 (for M Chambers).” Apple Books.
LiveView typo - Love the book btw
2019-06-07
67
TYPO
I think the code here: media.pragprog.com/titles/phoenix14/code/ecto/listings/rumbl/lib/rumbl_web/controllers/user_controller.change3.ex
Should read:
defmodule RumblWeb.UserController do
use RumblWeb, :controller
alias Rumbl.Accounts
alias Rumbl.Accounts.User
def index(conn, _params) do
users = Accounts.list_users()
render(conn, “index.html”, users: users)
end
def show(conn, %{“id” => id}) do
user = Accounts.get_user(id)
render(conn, “show.html”, user: user)
end
def new(conn, _params) do
changeset = Accounts.change_user(%User{})
render(conn, “new.html”, changeset: changeset)
end
def create(conn, %{“user” => user_params}) do
case Accounts.create_user(user_params) do
{:ok, user} ->
conn
|> put_flash(:info, “#{user.name} created!”)
|> redirect(to: Routes.user_path(conn, :index))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, “new.html”, changeset: changeset)
end
end
end
p 39: last paragraph “By default, our application starts […] controlls” => controls
p 76: last paragraph “Keep in mind […] excelent” => excellent
p 112: first paragraph “Digging deeper […] Ecto.Assocation.NotLoaded” => Ecto.Association.NotLoaded
p 189: 2nd to last paragraph “With Phoenix.Param properly implemented […] server back up” => server backup
p 223: First page of Chapter 11 2nd paragraph “Most successful projects […] neccesary” => necessary
p 247: end of first paragraph “Now if you start up […] eachother” => each other (more standard)
p 274: paragraph just after full code block “Nice! The first test […] funciton” => funky town jk, function, great song though no?
p 274: 3rd paragraph “You can see […] pure funcitons” => functions
2019-06-07
5,6
ERROR
For some reason when reading the MOBI version in the kindle.app (1.25.2 (52078)) on macos, the indentation for code snippets is correct, but not when using the kindle.app (6.16.1) on ipad (ios 12.1.4). Then the code snippets have lost indentation and the font looks extra bold.
Don’t know if this is a kindle.app issue or something that can be adjusted in the book’s formatting.
2019-07-21
I have sent this issue to the prags as a tooling bug report. Thanks for catching it. I am leaving this open until we get confirmation.
197
TYPO
The part “Though we place our implementation in the same file as the video definition, it could as easily exist elsewhere.” is incorrect. The example didn’t place the implementation in the same file as the video definition.
2019-06-07
217
ERROR
on the window.userToken snippet, the code calls Routes.static_url. However, the generated code on app.html.eex is using Routes.static_path. It is a bit confusing because I don’t know if this was updated in this snippet
2019-07-21
221
ERROR
When we generated our Multimedia context, the main file was created in rumbl/multimedia/multimedia.ex. However, the filepath in the book points to rumbl/multimedia.ex
2019-07-21
Updated your Phoenix version and the patches should match!
224
DEFER
I think it would be nice to have some explanation here around naming, because Phoenix.View.render_many and render_one need a function render() to be defined in the passed module, this may be not clear to the reader.
2019-06-07
230
TYPO
In this wrapping up, it says we built a server-side channel with support for both WebSockets and long-polling. However when the socket was created, it had “longpoll” set to false, so this affirmation is not true.
2019-06-07
255
ERROR
I’m trying to run the InfoSys.Cache example. I’ve previously built the app in B6.0 of the book. When I try to start the app in the umbrella/apps/info_sys directory, I get an error:
(Mix) Could not start application info_sys: InfoSys.Application.start(:normal, []) returned an error: shutdown: failed to start child: InfoSys.Supervisor
(EXIT) already started: #PID<0.171.0>
I’ve tried several methods to remediate the issue, but I’m not sure what the correct fix, or what I’m missing. The InfoSys app was done differently in B6.0, so maybe there’s some existing call somewhere, but I’ve been unable to identify it.
2019-06-08
258
TYPO
“let’s make our base supervisor in lib/rumbl/info_sys/supervisor.ex”: This path is incorrect because it points to “rumbl”. It should be “lib/info_sys” instead
2019-06-08
263
SUGGEST
This page contains a listing with the code for schedule_clear. However all this code was already presented on the previous listing. So if the reader copied all code of the previous listing, the cache is already expiring old values.
2019-06-08
241
ERROR
children = [
{Counter, 5}, # new counter worker
]
should be:
children = [
{InfoSys.Counter, 5}, # new counter worker
]
and the same for all the following occurrences.
2019-06-08
247
ERROR
iex> {:ok, agent} = start_link(fn -> 5 end)
should be:
iex> {:ok, agent} = Agent.start_link(fn -> 5 end)
2019-06-08
250
TYPO
The file path is wrong in the following paragraph:
<<Armed with what little we know about our supervision strategy, let’s make
our base supervisor in lib/rumbl/info_sys/supervisor.ex, like this:>>
Instead of “lib/rumbl/info_sys/supervisor.ex” it should be “apps/info_sys/lib/info_sys/supervisor.ex”.
2019-06-07
251
ERROR
Both the main application supervisor and the child supervisor are named InfoSys.Supervisor in the listing “otp/listings/rumbl_umbrella/apps/info_sys/lib/info_sys/application.change2.ex”:
or else the application will fail at start with the error:
[…]
failed to start child: InfoSys.Supervisor
(EXIT) already started: #PID<0.nnn.0>
2019-06-08
255
TYPO
The changes listed in “otp/listings/rumbl_umbrella/apps/info_sys/lib/info_sys/cache.change1.ex” are already included in listing “otp/listings/rumbl_umbrella/apps/info_sys/lib/info_sys/cache.ex” from page 253.
2019-06-08
257
TYPO
The path of the file is wrong in the following paragraph:
“Let’s create our interface in lib/rumbl/info_sys.ex, like this:”
It should be:
“Let’s create our interface in apps/info_sys/lib/info_sys.ex, like this:”
2019-06-08
272
ERROR
The tests from the listing “testing_otp/listings/rumbl_umbrella/apps/info_sys/test/cache_test.exs” do not work unless they are preceded with a “clear_interval” tag:
@tag clear_interval: 10
test “key value pairs can be put and fetched from cache”, %{name: name} do
[…]
@tag clear_interval: 10
test “unfound entry returns error”, %{name: name} do
[…]
2019-07-21
280
SUGGEST
Regarding the paragraph:
<<Let’s take the test with results. First, we spawn a Wolfram backend with
start_link. Next, we use assert_receive to ensure that the backend reports the
successful %InfoSys.Result{} that we asked for.>>
There is no spawning with start_link and also there is no assert_receive in the first test case. All the spawning is and checking the results is made inside the InfoSys module (with Task.yield_many). Probably the paragraph is describing an older version of the code.
Also, in the InfoSysTest module, the TestBackend.start_link/4 is not required. If it is commented, all the tests are still passing.
2019-06-08
281
TYPO
In the last paragraph on the page, there is no model_case in the code. Only data_case and conn_case.
2019-06-08
285
TYPO
On the last two paragraphs on the bottom of the page, you are describing the test “join replies with video annotations”, while in the above listing “testing_otp/listings/rumbl_umbrella/apps/rumbl_web/test/rumbl_web/channels/video_channel_test.exs” you are listing another test: “inserting new annotations”.
2019-06-08
287
TYPO
The test case “new annotations triggers InfoSys” from the listing “testing_otp/listings/rumbl_umbrella/apps/rumbl_ … umbl_web/channels/video_channel_test.change1.exs” from the middle of the page is already listed in the previous listing with the same name (also an error) from the previous page, 286.
2019-06-07
251
ERROR
Application starts the supervisor twice and crashes.
defmodule InfoSys.Application do
@moduledoc false
use Application
def start(_type, _args) do
children = [
InfoSys.Supervisor
]
opts = [strategy: :one_for_one, name: InfoSys.Supervisor]
Supervisor.start_link(children, opts)
end
end
2019-06-08
256
ERROR
The init function doesn’t produce a table of the module name. The code works if a new (named) table is created and passed as an option to the put or fetch functions. As written, returns put returns an ArgumentError
(stdlib) :ets.insert(InfoSys.Cache_cache, {“one plus one?”, “two”})
:ets.all() returns two #Reference tables, which I’m presuming is the generated table.
2019-06-08
255
TYPO
The “changes” (adding the schedule clear function and calling it from the handle_info(:clear, state) call) are already included in the code snippet from page 252-253.
2019-06-08
42
28
ERROR
In the second paragraph, you state that the application.ex file is lib/application.ex when it is actually in lib//application.ex. In this particular case, it is lib/hello/application.ex
2019-06-07
289
ERROR
There is exactly one occurrence of “model_case” in the whole book, and it is in this page. I don’t know what the book is referring to here
2019-06-07
55
41
TYPO
In the paragraph right before the listing for lib/rumbl/accounts.ex, second sentence, there is a missing word “of” after the word “couple”. It should say, “We’ll add a couple of functions …”.
2019-06-07
292
DEFER
On this page, default_video was created as a module attribute, but default_user was created as a function. Maybe use the same pattern on both to avoid confusion?
2019-06-08
218
ERROR
The generated UserSocket module from Phoenix has the connect function with this signature:
In the listing in this page where UserSocket is modified, this third param is not there. So in my case I forgot to remove this extra param when typing the code from the book and got an error later on in the book (around page 290) when running tests. I think it would be nice to add here that we should remove this param and maybe some explanation of why.
2019-06-08
295
TYPO
There’s a repeated listing in this page. The test “new annotations triggers InfoSys” was already added on previous listing. There’s two different explanations for the same listing, they could be merged.
2019-06-07
238
SUGGEST
I think it’s important to mention that this dep also needs to be added to rumbl_web project:
{:info_sys, in_umbrella: true}
2019-06-08
55
SUGGEST
The following sentences have redundancy that should be consolidated:
The mix ecto.gen.migration creates a migration file for us with a special timestamp
to ensure ordering of our database migrations. Note that your migration filename
is different from ours because Ecto prepends a timestamp to maintain
the ordering of migrations.
2019-06-07
94
ERROR
The end of page 94 says “Let’s logout and…”, but the logout functionality is only created a few pages later, thus we can’t (easily) logout yet.
Great job with the book, btw.
2019-07-21
223
TYPO
In the phrase: “but neccesary details of such a refactoring exercise”, “neccesary” is misspelled. It should be “necessary”.
2019-06-07
224
TYPO
In the sentence: “That way you can see one of the interesting aspects of observer, it’s ability to show a high level view of processes that can help you decide where to split an umbrella application.” It should be “That way you can see one of the interesting aspects of observer: its ability to show a high level view of processes that can help you decide where to split an umbrella application.” Notice the colon and the change of “it’s” to “its”.
2019-06-07
225
OK
In the sentences: “There’s more. Since communication happens with …”, I think it would be better to write it “There’s more: since communication happens with…”
2019-06-07
226
ERROR
iex -S mix phoenix.server
should be
iex -S mix phx.server
2019-06-07
261
SUGGEST
Suggestion.
By the time I got the InfoSys.compute working, I was confused about the supervision tree we set up. It looks like this: InfoSys.InfoSupervisor -> InfoSys.Supervisor -> InfoSys.TaskSupervisor -> (Wolfram backend). The names are very similar, and somehow it just didn’t gel to me why there are 3 layers of supervision. I felt like the OTP chapter made all of the layers of supervision really quickly and didn’t really explain that Task.Supervisor is a generic supervisor that we’re renaming. Not sure if others feel this way, but I think a little more explanation along the way of these different layers would help.
2019-06-08
125
SUGGEST
Text states: “We also import our Repo and Category.” Earlier text states “Importing Ecto.Query makes the…”. Code above the paragraph lists “import Ecto.Query” , “alias Rumbl.Repo” & “alias Rumbl.Multimedia.Category”. Is the statement saying we import our Repo and Category correct or should it say “We also alias our Repo and Category”?
2019-06-07
171
SUGGEST
For the listing in testing_mvc/listings/rumbl/config/test.change1.exs you change the config:
config :pbkdf2_elixir, :rounds, 1
so that the tests aren’t slow. I saw this slowdown as soon as I started testing “logged in users” on page 161. You should move this optimization to that page. It’s what I did, because I read the chapter first, then went back and ran the exercises with a re-read.
2019-06-07
161
ERROR
This is a duplicate of #84698 from B6.0, I’m just adding more context. For the listing: testing_mvc/listings/rumbl/lib/rumbl_web/controllers/auth.change1.ex you use this line in the condition block:
user = conn.assigns[:current_user] ->
conn
Doing so results in a warning, as the very next line rebinds user. Here’s the warning:
Compiling 7 files (.ex)
warning: variable “user” is unused (if the variable is not meant to be used, prefix it with an underscore)
lib/rumbl_web/controllers/auth.ex:17
I’m marking this as a technical error but maybe that’s too harsh :-)
2019-06-08
69
TYPO
iex> -r Rumbl.Accounts.User
should be
iex> r Rumbl.Accounts.User
2019-07-21
296
SUGGEST
Add a graphic/image of our goal InfoSys supervision tree. It’ll give a visual context of how the pieces go together.
2019-06-07
No time.
249
DEFER
Add a graphic/image of the goal InfoSys supervision tree. It’ll give a visual context of how the pieces go together.
2019-07-21
269
TYPO
“Note we’re using our user-facing create_user function instead of the user-facing
register_user function.”
Should maybe be:
“… our API-facing… instead of the user-facing…”
2019-06-08
285
SUGGEST
After adding this listing testing_otp/listings/rumbl_umbrella/apps/rumbl_web/test/rumbl_web/channels/video_channel_test.exs
I consistently got this error:
Compilation error in file test/rumbl_web/channels/video_channel_test.exs
(CompileError) test/rumbl_web/channels/video_channel_test.exs:3: module RumblWeb.TestHelpers is not loaded and could not be found
I had to add this to apps/rumbl_web/test/test_helper.exs
Code.require_file “../../rumbl_web/test/support/test_helpers.exs”, DIR
Once I did that it compiled and the everything worked as expected.
2019-06-08
118
TYPO
Not sure if this is the right page number. The `get_user_video!/2` function here includes a line I think is missing in the code download for the Testing MVC chapter.
Inside the `code/testing_mvc/rumbl/lib/rumbl/multimedia.ex` file, the `|> user_videos_query(user)` line from this page is missing from inside the `get_user_video!/2` function.
2019-06-08
96
ERROR
This logout link will not work because Phoenix HTML changes the method from `delete` to `post` because the HTML spec only supports get/post/dialog methods in a `
2019-07-21
Phoenix has something called Plug.MethodOverride in your endpoint, which uses the method given in _method to be your application method. So everything should work, since we do pass the _method as parameter which should be rewritten.
33
ERROR
When I run
mix phx.new hello
I have to manually add “cd assets && npm install …”
The console output on page 33 indicates that this happens automatically.
2019-06-07
56
ERROR
Footnote link to documentation of ecto migration is wrong
2019-06-07
67
SUGGEST
We now have a literal dependency on Ecto.Changeset in our web controller. Two pages earlier there was an extra aside regarding not coupling form_for to Ecto. Effectively we leaked persistence details into the fronted code.
2019-06-08
The note about coupling between form_for and Ecto is not from the perspective that `form_for does not know about changeset, because it does, but rather that form_form does not work *only* with changesets. Your domain and the web part need to agree on which data structure they will use to portray changes, errors, etc, and the changeset is this data structure.
\n
\nThe fact that Ecto 3 ships with a persistence layer out of the box aims to show you can use Ecto for casting/validation without having to persist anything anywhere.
74
OK
Tweaking xxx_create_credentials.exs to reference :users breaks the generated test scripts.
In general, there is suspiciously little testing in these chapters. When there is, it’s done via iex.
At least some commentary like "tests break here, we’re gonna fix them in chapter 42’ or something would be nice.
2019-06-08
We don't write tests as we go along so we can discuss Ecto and Phoenix concepts without a lot of disruption - although in real life, they would go side by side. We discuss exactly this in the testing chapter.
\n
\nWe do know that some resources can do development and testing side by side but after a couple tries we found it best to not go this route for this particular book.
79
OK
Updating existing users with properly hashed temporary passwords and placeholder emails should probably be a migration, not something someone does (or forgets to do during deployment) on a console.
2019-06-07
76
TYPO
typo:
OWASP has an excelent set …
correct:
OWAS has an excellent set …
2019-06-07
55
TYPO
“allow us to work more easy with changesets” should be “allow us to work more easily with changesets”.
2019-06-07
86
72
SUGGEST
Update comeonin and pbkdf2_elixir to their latest versions. i.e.
defp deps do
[
…,
{:comeonin, “>= 5.1.1”}, # instead of 4.1
{:pbkdf2_elixir, “>= 1.0.2”} # instead of 0.12
]
end
2019-06-08
77
ERROR
I could not get the function put_pass_hash/1 to work (maybe because I try to many things at the same time as reading ..?), my problem was that the field password_hash is marked as “not null” in database and that the changeset was always valid? = false.
I changed my function to following to get it to work:
defp put_pass_hash(changeset) do
pass = get_change(changeset, :password)
case pass do
nil -> changeset
_ -> put_change(changeset, :password_hash, Comeonin.Pbkdf2.hashpwsalt(pass))
end
end
2019-06-08
39
TYPO
« This tree is a piece of code that controlls » —> controls.
2019-06-07
41
TYPO
« We’ll add a couple functions which allows […] » —> allow.
Unless you meant « Adding a couple functions allows » (the fact of adding those functions allows XYZ), in which case I’d advocate using a coma : « We’ll add a couple functions, which allows […] ».
2019-06-07
127
ERROR
On page 127, it’s suggested that we do the following:
def alphabetical(query) do
from c in query, order_by: c.name
end
def list_alphabetical_categories do
Category
|> Category.alphabetical()
|> Repo.all()
end
However, that gives me the following error: “lib/rumbl/multimedia/category.ex:19: undefined function c/0”
line 19 is the middle line of Category.alphabetical/1.
I’ve found the following code to work:
def list_alphabetical_categories do
query = from c in Category, order_by: c.name
Repo.all(query)
end
It seems important to the compiler that `````“from c in Category, order_by: c.name” by assigned to something. I do not know why.
Hopefully this is helpful. Sorry if it is a duplicate, I did not have time to read through all the currently submitted errata and there is not a search function.
2019-06-08
23
ERROR
“[name: name] is shorthand for [{name: name}] .” Should this not be: [name: name] is shorthand for [{:name, name}] .
2019-06-07
37
TYPO
“We need to do one more bit of housekeeping.” => bits
2019-06-07
212
TYPO
The top of page 212 says “Remember to update your repository by running migrations:” and then “And now you can migrate your database:”, both with the “mix ecto.migrate” code sample.
2019-06-07
66,92
SUGGEST
I made it to page 92 without understanding the “Routes.some_path” bit (from page 66 — the first time it is actually explained). At this point in the book (page 92), “Routes.page_path(conn, :index)” had become confusing. It took the online Phoenix guides to straighten me out on the matter. The path-helpers section of the guide helped, but it really clicked when seeing the more-on-path-helpers section with the “mix phx.routes” output. Which I promptly ran on my machine and realized what (I) had been missing.
TLDR:
“Routes.some_path” from page 66 may not be explained well enough as to how it works.
I’m not sure if page 66 is the correct place to explain it; however it seemed to be the only place that it was explained.
2019-06-07
129
ERROR
With regards to Ecto queries: “In Elixir, the ^ operator (called the pin operator) means we want
to match against this specific version of ^username rather than binding to
the username variable.” Ecto’s documentation states that the ^ (caret) is used for injecting a value or expression for interpolation (as part of it’s DSL) seen at: hexdocs.pm/ecto/Ecto.Query.html#module-interpolation-and-casting
2019-06-08
153
164
TYPO
“We close by trying to register two identical users, then asserting the accounts
system claims our username has already been taken.”
In the testing_mvc/listings/rumbl/test/rumbl/accounts/accounts_test.exs file, the enforce unique usernames test should either be the last test in the describe block, or the wording should change to “We close by setting a password that is too short and then test for a specific error.” (from the previous paragraph)
2019-06-07
30
SUGGEST
José mentioned 8080 (HTTPS) as alternative, additional endpoint. There is nothing inherently wrong with it, but it might be better to use 8080 port in that example accordingly it’s expected use: alternative “plain” HTTP port. Optionally, change port to 8443 and leave it as HTTPS port.
Again: It’s not a part of any standard, it’s not a mistake per se, book is not really suffering because of it, but this is not something you will expect in most of the real life situations.
2019-06-07
230
SUGGEST
This whole section on copying files around is pretty much ignorant of version control. This approach will lose all history for files etc. Granted, this is a book about phoenix and elixir and not about revision control systems, but still.
2019-06-07
231
ERROR
rumbl_umbrella/apps/rumbl/
lib/rumbl/application.ex needs more clean up than mentioned in the text.
My file still contained
Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
RumblWeb.Endpoint.config_change(changed, removed)
:ok
end
at this point, which needs to be removed. The compiler will also warn about this.
2019-06-08
247
ERROR
The text says to change lib/rumbl/application.ex, but the listing says rumbl_umbrella/apps/info_sys/lib/info_sys/application.ex
In general the preceding section is somewhat imprecise regarding which files are changed in which step
2019-06-08
251
SUGGEST
Each of our supervisors will have two
children, first a Task supervisor to spawn tasks isolated under their own
supervisor, followed by a InfoSys.Cache GenServer,
The code has the order of children the other way around.
2019-06-08
250
SUGGEST
Text says “We also pass the initial state of an empty list, which
we don’t intend to use. ”
Code does not pass an empty list. Arguably opts could be bound to an empty list at runtime, but that’s not guaranteed.
2019-06-07
264
SUGGEST
On this page the InfoSys.Result struct suddenly stops containing an url field. Previous results always contained an url field, which is always nil. So maybe remove the url from the struct e.g. on page 257
2019-07-21
259
SUGGEST
The text says
The compute function
takes a String.t query, a Keyword.t list of options, and returns a type we’ll define
later called InfoSys.Result.t.
But the type InfoSys.Result.t is already defined two pages earlier.
2019-07-21
274
TYPO
funciton should be function
2019-06-07
275
ERROR
Regarding the TestBackend module, the text says “Since our backends are tasks, we’ll need to fire up a task in start_link.”
Why do we need to fire up a task? The given start_link implementation can be replaced by one that does nothing except raising an exception without affecting any test (i.e. TestBackend.start_link does not seem to even get called anywhere). The actual wolfram implementation itself is not concerned about task handling, why should its test replacement?
2019-06-08
255
ERROR
When trying to run the code in iex listed on page 255, where you take the cache for “a test spin”, I get the following error when running “Cache.put(”one plus one?“, ”two“)”:
When running the “InfoSys.compute(”what is elixir?“)” in iex, the following error appears:
iex(1)> InfoSys.compute(“what is elixir?”)
(exit) exited in: GenServer.call(InfoSys.TaskSupervisor, {:start_task, [{:nonode@nohost, #PID<0.405.0>, #PID<0.405.0>}, [#PID<0.405.0>], :monitor, {InfoSys.Wolfram, :compute, [“what is elixir?”, [limit: 10]]}], :temporary, :brutal_kill}, :infinity)
(EXIT) no process: the process is not alive or there’s no process currently associated with the given name, possibly because its application isn’t started
(elixir) lib/gen_server.ex:979: GenServer.call/3
(elixir) lib/task/supervisor.ex:447: Task.Supervisor.async/6
(elixir) lib/enum.ex:1327: Enum.“map/2-lists^map/1-0”/2
2019-06-08
230
SUGGEST
“We’ll need all three of the dependencies, :comeonin , :pbkdf2_elixir and :sweet_xml .” You talk about sweet_xml here like it was previously a dependency — it was not. Page 230 was the first time anything was even mentioned about the XML parser. Perhaps consider reworking this into where it is actually introduced / used in the book.
2019-06-07
232
ERROR
“Oops. That didn’t work as we’ve not yet fetched dependencies. We’ll have to run it later after we’ve fetched our dependencies.” Everything here runs fine, in fact the only commands we are running are to change directories and to fetch dependencies… Perhaps this is a hold over from an earlier version of the book?
2019-06-07
251
TYPO
“Now you’re ready to add the new supervisor into our application’s supervision
tree in lib/rumbl.ex , like this:
otp/listings/rumbl_umbrella/apps/info_sys/lib/info_sys/application.change2.ex”
The path “lib/rumbl.ex” is wrong. The path should be “info_sys/application.ex”.
2019-06-08
258
TYPO
“callback name() :: String.t" does not follow the convention of mix format or the rest of the code sample. It should be "callback name() :: String.t()”
2019-06-08
259
SUGGEST
1. “Create a config/dev.secret.exs file and include your WolframAlpha key under
Mix.Config under the top-level umbella app”
2. “When you ran mix phx.new , phoenix generated a .gitignore entry to ignore all
*.secret.exs files inside your config directory.”
You should really consider making it clear that you mean rumbl_umbrella/apps/rumbl/config/dev.secret.exs
Your wording here could lead some to put this in the top level rumbl_umbrella/config directory.
Also, typo: “umbella” should be “umbrella”.
2019-06-08
116
TYPO
It says “Then, the list_user_videos and get_user_videos utility functions”, but then we define get_user_video (singular).
2019-06-08
9
TYPO
LiveVeiw should be LiveView
2019-06-07
279
SUGGEST
“let’s require the file in each test suite. Add the
following line to the top of your rumbl_umbrella/apps/info_sys/test/test_helper.exs :”
You say that it should be done in each test suite, then you only mention one file. Consider making this more explicit as this is needed for the test to run properly.
2019-06-08
279
SUGGEST
Per my previous Erratum on this page, I believed that the entry was needed in the second file. However it appears to not be needed and was an issue with mix. In either case, this step should be cleared up.
2019-06-07
284
TYPO
“testing_otp/listings/rumbl_umbrella/apps/rumbl_web/test/support/test_helpers.exs”
should be file extension “ex” — not “exs”
2019-06-08
122
TYPO
It says “and create an unique index for it” - the word “an” should be “a”.
2019-06-07
126
TYPO
The sentence doesn’t make sense:
“We’ll put query functions in our schema layer and leave complex interactions, such as those between our multimedia and users will go in in contexts to leave con- trollers as thin and simple as possible.”
2019-06-07
133
ERROR
Chapter 5, accounts.change2.ex:
The functions “Comeonin.Pbkdf2.checkpw” and “Comeonin.Pbkdf2.dummy_checkpw” are now removed.
Their alternatives are “Pbkdf2.verify_pass” “Pbkdf2.no_user_verify” in that order.
2019-06-08
251
ERROR
The registered name of the module InfoSys.Supervisor is the same as the name in the InfoSys.Application module which causes a runtime error.
2019-06-08
José?
177
178
ERROR
test “authenticate_user halts when no current_user exists”, %{conn: conn} do
conn = Auth.authenticate_user(conn, [])
assert conn.halted
end
This test fails with an error:
“key :current_user not found in: %{}”
In a line which has code “if conn.assigns.current_user do”
I think this should have worked as the condition is checking the presence of the key but I am not sure why this is failing.
2019-06-08
149
OK
To avoid confusion with the generated test_helper.ex, I suggest to rename the test_helpers.ex to something else.
2019-07-21
55
SUGGEST
hould suggest and tell people to use :utc_datetime instead of the default timestamps()?
2019-06-08
Hi Ken, I agree :utc_datetime is important. However there are only so many things we can talk about in the book. For example, a discussion on :decimal would be extremely important as well but we can't fit it all in. Hopefully other books such as the Ecto book and the official documentation give those topics the attention they deserve.
93
ERROR
Now the latest version of the API for Comeonin and Pbkdf2 are different:
def authenticate_by_email_and_pass(email, given_pass) do
user = get_user_by_email(email)
cond do
user ->
case Pbkdf2.check_pass(user.credential, given_pass) do
{:ok, _} ->
{:ok, user}
_ ->
{:error, :unauthorized}
end
true ->
Pbkdf2.no_user_verify()
{:error, :not_found}
end
end
2019-07-21
105
SUGGEST
1. In testing `authenticate_user`, error occurs:
Why not change `conn.assigns.current_user` to `conn.assigns[:current_user]` to make the code more robust but to assign `nil` in test case?
2019-06-08
217
OK
In `scheduleMessages`, there is typo for `this.schedulerTimer` and `this.scheduleTimer`. An extra `r` is added.
2019-06-07
220
OK
For the `lastSeenId`, I don’t think it’s good to set it when receiving “new_annotation” event, as it might be a much later event message from others whose is watching and commenting. Also, collecting the max ids when joining the channel cannot represent the real max id I have seen.
I think it’s better to set the `lastSeenId` in `renderAtTime` before rendering annotation. And so the definition of it should be moved out of `Video` object’s definition as a global variable.
To cater the case that the user is posting the comment himself, we can set the retrieved & filtered annotations to be instance variable and add his posted comments into it to utilize the same `scheduleMessages` method.
2019-06-07
219
DEFER
Whole UI will be refreshed when restarting with `mix phx.server`, there maybe channces that we cannot see the effect of loading duplicate annotations if we don’t keep an eye on the page. I think you may remind the reader about this.
2019-07-21
223
TYPO
Duplicate `and` exists in:
>Both the channels and and the MVC
2019-06-07
232
SUGGEST
Moving Assets
1. We should also move the css file as well.
2019-06-08
232
ERROR
`cd ..` should not be the correct command to go back to umbrella project root to test both apps. Last statement of below code should be updated.
cd apps/rumbl_web/assets
npm install
cd ..
2019-06-08
247
ERROR
for the `:one_for_all` change, which `application.ex` should be updated? In which folder should I run `iex -S mix phx.server`? When I change the one in info_sys and run the command in umbrella folder, it’s complaining the error `module Repo was given as a child to a supervisor but it does not exist`.
2019-06-08
251
TYPO
add the new supervisor into our application’s supervision tree in `lib/rumbl.ex` (Location 9760), should be changed to `lib/info_sys/application.ex`?
2019-06-08
251
ERROR
The name of the application should be changed? Else the application failed to start with error: `already started`. The `opts = [strategy: :one_for_one, name: InfoSys.Supervisor]` should be changed to `opts = [strategy: :one_for_one, name: MODULE]`?
2019-06-08
255
ERROR
`cache.ex` already includes every about scheduling for cache expiration in the first place (Page 254), then the paragraphs in page 255 & 256 about changing the state to includes `timer` seems not necessary. Should the first place not including that piece of logic?
2019-06-08
275
ERROR
Why the `TestBackend` need to have `start_link` function defined? Shouldn’t it implement the `Backend` behaviour? It seems I can run the test successfully without the `start_link` function.
2019-06-08
280
ERROR
The testing code doesn’t seem to match the paragraphs in the book. No code needs to spawn the Wolfram backend and use `assert_receive`. It’s all encapsulated in InfoSys, isn’t it?
2019-06-08
284
ERROR
Wrong default value of `insert_video` in `test_helpers.exs`, should change the `[]` to `%{}`
def insert_video(user, attrs \\\\ []) do
2019-06-08
285
TYPO
typo `video:#{vid}` to `videos:#{vid}` in below paragraph:
>Then we call the `subscribe_and_join` test helper to attempt to join the channel
>responsible for the `video:#{vid}` topic.
2019-06-08
285
SUGGEST
I don’t see which part of the code refers to this paragraph:
>Next, we make sure we’ve joined the right topic by comparing the video ID from our connected test socket with the one returned from our test helper.
2019-06-08
171
SUGGEST
The suggestion to configure the tests like this
`config :pbkdf2_elixir, :rounds, 1`
for the tests to run faster should be mentioned much earlier. I was wondering the whole time why the hell everything is so slow, until i finally read that particular section of the book.
2019-06-07
259
TYPO
use Mix.Config
config :rumbl, :wolfram, app_id: “12345-6789”
I had to change ‘:rumbl’ to ‘:info_sys’, otherwise the app_id returned by InfoSys.Wolfram.id function is blank and the Wolfram query fails with a DOWN process status.
Contrary to a previous comment, I was unable to put the dev secret in the rumbl config folder, since with the new umbrella structure, all config has been moved to top-level umbrella directory.
2019-06-08
248
SUGGEST
I find the following statement under “Registering Processes” a bit vague:
“Our named process can be either local, meaning visible to a single node, or global, meaning visible to all connected nodes. OTP automatically provides this feature with the :name option in start_link.”
It mentions the two visibility modes (local, global), but then offers no explanation on how to do that.
2019-06-08
286
ERROR
test “new annotations triggers InfoSys”, %{socket: socket, video: vid} do
19:11:57.288 [error] Task #PID<0.368.0> started from #PID<0.367.0>
terminating
(UndefinedFunctionError) function InfoSys.compute/2 is undefined
(module InfoSys is not available)
InfoSys.compute(“1 + 1”, [limit: 1, timeout: 10000])
(rumbl_web) lib/rumbl_web/channels/video_channel.ex:59:
RumblWeb.VideoChannel.compute_additional_info/2
(elixir) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Function: #Function<1.42554334/0 in RumblWeb.VideoChannel.handle_in/4>
Args: []
2019-07-21
286
ERROR
in general, when running mix test from rumbl_umbrella/apps/rumbl_web/
I receive the following message:
warning: function InfoSys.compute/2 is undefined (module InfoSys is not available)
lib/rumbl_web/channels/video_channel.ex:59
Apparently the executing test script is trying to reference the line:
defp compute_additional_info(annotation, socket) do
for result <- InfoSys.compute(annotation.body,
…
in rumbl_umbrella/apps/rumbl_web/lib/rumbl_web/channels/video_channel.ex, probably because
info_sys is a separate app and cannot be seen during this script execution.
2019-06-08
280
ERROR
Running the following rumbl_umbrella\\apps\\info_sys\\mix test
produces the following output:
1) test makes request, reports results, then terminates (InfoSys.Backends.WolframTest)
test/backends/wolfram_test.exs:4
(ArgumentError) argument error
code: actual = hd InfoSys.compute(“1 + 1”, [])
stacktrace:
:erlang.hd([])
test/backends/wolfram_test.exs:6: (test)
….
Finished in 1.6 seconds
10 tests, 1 failure
Randomized with seed 94000
2019-06-08
230
SUGGEST
One of the most confusing aspects of this book is the splitting up of the rumbl app into its respective places within the umbrella parent app.
According to your book instructions, all configuration is to take place at the parent level. However, upon perusing the code supplied on the website, this has a completely different organisation, where in rumbl_umbrella/config.exs one reads, … # By default, the umbrella project as well as each child
application will require this configuration file, as
configuration and dependencies are shared in an umbrella
project. While one could configure all applications here,
we prefer to keep the configuration of each individual
child application in their own app, but all other
dependencies, regardless if they belong to one or multiple
apps, should be configured in the umbrella to avoid confusion.
import_config “../apps/*/config/config.exs”
, which leads one to believe that we need config sections in both rumbl and rumbl_web (… and info_sys … ) sub-apps.
I am trying to follow your instructions as per the book, and now I have what appears to be 3 isolated apps with config at the umbrella level. Is this correct, or will it now lead to warnings that other sub-app components can’t be found?
Also, you point out in the book that the ‘rumbl_web’ sub-app can reference the ‘rumbl’ sub-app by means of the in-place in-umbrella reference in its own mix.exs. So is one to understand that all testing code in rumbl_web can freely reference rumbl components. But what happens when said rumbl components want to reference rumbl_web, for example in application.ex there is a call to rumbl_web to update its config if the rumbl app changes, but surely this will produce warnings that rumbl_web is not available? And later on in the book, if we are to follow this config method, what happens when say rumbl_web wishes to reference info_sys sub-app components?
I’m only asking these questions to try to clarify how one goes about referencing sub-apps from others in without encountering warnings.
2019-07-21
You are correct! We have fixed this in recent editions by putting all configuration in a single place (the umbrella root). No more ad-hoc rules about what goes where!
239
SUGGEST
“The new rumbl child app does not have a web component” … so shouldn’t we also comment out the line: ?
def config_change(changed, _new, removed) do
# Commented out, since this app no-longer has a web component.
# RumblWeb.Endpoint.config_change(changed, removed)
:ok
end
Could you clearify
1. what this `@tag clear_interval: 60_000` is doing
2. how ExUnit prevents the `eventually` function from running forever, if `func` is not returning what we expect
2019-07-21
233
SUGGEST
extract of comments residing in from rumbl/config/config.exs generated by “mix phx.new rumbl —umbrella”
By default, the umbrella project as well as each child
application will require this configuration file, as
configuration and dependencies are shared in an umbrella
project. While one could configure all applications here,
we prefer to keep the configuration of each individual
child application in their own app, but all other
dependencies, regardless if they belong to one or multiple
apps, should be configured in the umbrella to avoid confusion.
this expresses the opinion of authors of “mix” to configure most child app config in the child apps themselves
please clarify - if needed - in the chapter
2019-07-21
79
SUGGEST
Readers may copy the minimum password validation without ever checking OWASP. The min should be increased from 6 to 16 for safety.
2019-07-21
Fair point. We don't want to chase OWASP here but we should mention that these rules are lax in a warning.
11
SUGGEST
“because it supports a feature called lightweight processes. You can create hundreds of thousands of processes without breaking a sweat” repeats anecdote from Concurrency is Hard, but not by emphasizing the point and instead acting like this is the first mention of Processes.
2019-07-21
11
SUGGEST
“because it supports a feature called lightweight processes. You can create hundreds of thousands of processes without breaking a sweat” repeats anecdote from Concurrency is Hard, but not by emphasizing the point and instead acting like this is the first mention of Processes.
2019-07-21
324
315
TYPO
Line: 3 ``and …“to think about sending datata between the client and the server.”
Should be data.
2019-07-21
113
TYPO
After the snippet of code for the create function one can read:
“That’s simple enough. We create a user with the create_video function and then redirect if it’s successful,”
I think it should be:
“That’s simple enough. We create a VIDEO with the create_video function and then redirect if it’s successful”
2019-07-21
126
TYPO
Where it says: “We also import our Ecto.Query module and alias Repo and Category. ”
Should be: “We also import our Rumbl.Repo module and alias Repo and Category.”
I think :D
2019-07-21
5
TYPO
“onother” instead of “another”. It’s in the sentence that starts with “If your machine has more than one core…”
2019-07-18
7
TYPO
“And while this is just one example, we have the option to make similar trade-off at different times in our stacks.”
I think it should read “similar trade-offs” (with the “s”).
Hi Patrick! For now we are working with hardcoded entries and the hardcoded entries contains strings as ids. So it should be correct. Thanks for reaching out!
113
TYPO
The following phrase “We create a user with the create_video…” should be “We create a video with the create_video”…
The test “requires password to be al least 6 characters long” should be rewritten al follows:
test “requires password to be at least 6 characters long” do
invalid_credentials = Map.put(valid_attrs[:credential], :password, "12345")
invalid_attrs = Map.put(valid_attrs, :credential, invalid_credentials)
assert {:error, changeset} = Accounts.register_user(invalid_attrs)
assert %{credential: %{password: [“should be at least 6 character(s)”]}} = errors_on(changeset)
assert [] = Accounts.list_users()
end
2019-07-21
34
TYPO
A sentence in chapter 2 refers to a rumbl directory where it should refer to hello instead. “Support for starting, stopping, and supervising each application is in lib/rumbl/application.ex.” Should be “lib/hello/application.ex.”
2019-07-21
113
TYPO
> We create a user with the create_video function
Should read
We create a video with the create_video function
2019-07-21
113
ERROR
Paragraph at the end of the page.
`That’s simple enough. We create a user` ——> `That’s simple enough. We create a video`
2019-07-21
239
ERROR
:comeonin is no longer a required dep. In general, since v5 of Comeonin no longer requires direct use (we use pbkdf2_elixir directly instead), it might make sense to no longer refer to it.
2019-07-21
79
ERROR
The method ``registration_changeset does not validate_required([:password]) which will allow blank passwords and bypass the length requirement. It should be added.
2019-07-21
96
ERROR
In the “new.html.eex” section, the closing tag for the form_for code injection is on a new line.
I have a compile error that goes away when I put the tag after the “fn f ->” part.
Compile error:
lib/rumbl_web/templates/session/new.html.eex:7: missing terminator: end (for “fn” starting at line 6)
2019-07-21
49
TYPO
supervising each application is in lib/rumbl/application.ex
should be
supervising each application is in lib/hello/application.ex
In the context of things, correct?
2019-07-21
224
TYPO
“Our” repeated in “our our socket”
2019-07-18
228
TYPO
“Our presence data now has friendluy usernames.” should have “friendly” instead of “friendluy”.
2019-07-18
237
ERROR
Found two errors in the Umbrella chapter.
1. You need to update presence.ex to :rumbleweb otp app and RumblWeb.PubSub
2. When copying the assets, there is no instruction to copy the css files.
2019-07-21
243
TYPO
In “ We used Observer to understand the important behind applications.” “important” should be “importance”.
2019-07-18
76
ERROR
The validation code doesn’t actually cover the unique index on username, so the form isn’t actually “done” at this point.
Adding |> unique_constraint(:username) to changeset() will resolve the issue and give a validation error on the form properly instead of exploding.
2019-07-21
172
ERROR
In the code example you have a “renders new.html” test inside video_view_test.exs. The first line in the test creates “owner” but “owner” isn’t used after that so it throws a warning in the console. Also, this book is awesome.
2019-07-21
275
266
ERROR
The path in the code listing for info_sys.ex is wrong. It should be in the info_sys folder, not the the info_sys/lib folder.
2019-07-21
93
ERROR
Actually, Pdfbk now has an even simpler API that renders the whole cond unnecessary, as it will by default call the fake verify when the user exists, and returns the {:ok, user} or {:error, msg}
so the func can just be…
def authenticate_by_username_and_pass(username, given_pass) do
user = get_user_by(username: username)
Pbkdf2.check_pass(user, given_pass)
end
2019-07-21
Yes, the new API is neat but we can to keep returning relevant semantic errors such as {:error, :unauthorized} and similar. But using the function also works! Thanks!
60
TYPO
At it’s core => At its core
2019-07-18
80
ERROR
The registration_changeset/2 function checks the password’s length. I tried the code but if the password is empty, I have the following error: “null value in column ”password_hash" violates not-null constraint". I have to add an additional constraint: validate_required([:password]) in order to avoid the crash.
2019-07-21
428
ERROR
After forming umbrella project any test that uses video_fixture from test helpers are broken. It seems video_fixture insert the record but the id of returning record is nil. I changed the schema definition of video and added the option :read_after_writes like following:
@primary_key {:id, Rumbl.Multimedia.Permalink, auto_generate: true, read_after_writes: true}
All tests are passing.
2019-07-21
295
ERROR
I downloaded code for the book, setup it and run “mix test”. Tests pass, but there are errors in console for “video_channel_test”. This error gone when i commented the line 31 in “video_channel.ex”:
[error] Task #PID<0.552.0> started from RumblWeb.Presence_shard0 terminating
(stop) exited in: DBConnection.Holder.checkout(#PID<0.547.0>, [log: #Function<11.21419755/1 in Ecto.Adapters.SQL.with_log/3>, source: “users”, timeout: 15000, pool_size: 10, pool: DBConnection.Ownership])
(EXIT) no process: the process is not alive or there’s no process currently associated with the given name, possibly because its application isn’t started
2019-07-21
296
TYPO
Code for the book contains a test “join replies with video annotations” inside “video_channel_test.exs” file, but there is no such a test in “Testing Channels and OTP” chapter.
2019-07-21
96
OK
When I submit the login form with wrong credentials, the login form retains the email (but not the password). Explain from where the email is retrieved.
2019-07-21
111
96
ERROR
The new.html.eex snippet has, I believe, a syntax error. It is shown as:
Without that a syntax error is presented that is hard to figure out:
(TokenMissingError) lib/rumbl_web/templates/session/new.html.eex:6: missing terminator: end (for “fn” starting at line 5)
2019-07-21
34
ERROR
Has “lib/rumbl/application.ex” instead of “lib/hello/application.ex”
2019-07-21
80
ERROR
The code for the registration_changeset found in chapter 5 has a bug media.pragprog.com/titles/phoenix14/code/authentication/listings/rumbl/lib/rumbl/accounts/user.change1.ex. The code will block registration if the password is very short - but will allow the registration if the password is blank. Need to add validate_required() to the pipeline to make sure that the password is present after casting the params into the changeset.
2019-07-21
28
ERROR
In the book, the message was:
please define a clause for render/2 or define a template at “lib/hello_web/templates/hello”.
But I received:
please define a matching clause for render/2 or define a template at
2019-07-21
82
ERROR
“Repo.update!(User.registration_changeset(u, %{password: ”temppass“})” is missing a parens.
2019-07-21
100
SUGGEST
In “Wrapping Up” the third bullet point states:
> We briefly introduced relationships.
However, the concept of relationships has not been introduced.
2019-07-21
96
SUGGEST
We are advised to log out:
> Let’s logout and visit /sessions/new in our browser to try some login attempts.
However, we have not yet built the logout functionality which makes it difficult to do so unless we delete the browser cookies.
2019-07-21
96
SUGGEST
In Line 6 of the code example the code “%>” starts at the first column of a new line. If this is replicated in code, I receive this error:
Compilation error in file lib/rumbl_web/views/session_view.ex
(TokenMissingError) lib/rumbl_web/templates/session/new.html.eex:7: missing terminator: end (for “fn” starting at line 6)
moving the “%>” to directly after “fn f ->” (instead of at the start of a new line) allows the template to compile.
2019-07-21
113
TYPO
“We create a user with the create_video function”. Should be “We create a video…”.
2019-07-23
97
82
TYPO
iex> for u <- Repo.all(User) do
…> Repo.update!(User.registration_changeset(u, %{password: “temppass”})
…> end
Second line is missing a closing parenthesis
2019-07-23
34
TYPO
The application.ex file is listed as lib/rumbl/application.ex, but it should be lib/hello/application.ex (the example project rumble is introduced in the next chapter, this chapter’s project is called hello).
2019-09-26
203
TYPO
> We extract the video ID useing pattern matching: “videos:” <> video_id will math all topics starting with “videos:” and assign the rest fo the topic to the video_id variable.
Should be of and not fo.
2019-09-26
223
TYPO
channels spelled chanenls when specifying file:
lib/rumbl_web/chanenls/video_channel.ex
should be
lib/rumbl_web/channels/video_channel.ex
(First paragraph, second sentence after heading “Tracking Presence in Channels”
2019-09-26
267
ERROR
In the second paragraph it says there is a :url field on the result struct but that was not included on the previous page.
2019-09-26
Duplicate of #85793.
269
ERROR
Application.fetch_env!(:rumbl, :wolfram)[:app_id] on line 39 of the code sample should be :info_sys instead of :rumbl
2019-09-26
240
SUGGEST
In the Copying the Web Source Files section, users need to add RumblWeb.Presence to the list of supervised children and make some changes to RumblWeb.Presence, most notable the :otp_app and RumblWeb.PubSub.
Then in the moving assets section on 241, readers haven’t been directed to perform mix deps.get before being instructed to run npm install. However after they are directed to run npm install, they are directed to do mix deps.get and then run npm install again. This needs to be cleaned up because it is super confusing.
That being said, everything has been super helpful so far.
2019-09-26
295
ERROR
the mix test command at the bottom of the page intermittently produces an error:
mix test test/rumbl_web/channels/video_channel_test.exs
.
In addition to this, if you run mix test for the entire umbrella you receive this error:
23:19:47.326 [error] Task #PID<0.589.0> started from RumblWeb.Presence_shard0 terminating
Good catch! Basically the Presence wants to query the DB and send updates but the test has shut down and there are no database connections. To fix this consistently, we would need to query the presence supervisor and ask all of its children to shutdown at the end of each test. But to do so, we will need to add a new API to Phoenix. If you can open up an issue in Phoenix issues tracker, it would be extra helpful. Thank you!
391
ERROR
While following along with chapter 12 I tried to test the information services annotation creation but got an error on Presence: “ArgumentError: :ets.lookup(RumblWeb.Presence, :pool_size)” and a traceback to the “RumblWeb.Presence.list” call in video_channel.ex.
After some searching I found the cause: while creating the umbrella app the rumbl_umbrella/apps/rumbl_web/lib/rumbl_web/channels/presence.ex is copied from the old app and thus misconfigured to use the “otp_app: rumbl”, which should be “otp_app: rumbl_web” now. Similarly “pubsub_server: Rumbl.PubSub” should read “pubsub_server: RumblWeb.PubSub”.
Apologies if this is covered elsewhere and I missed it.
Thank you for an amazing book!
2019-09-26
92
74
ERROR
The changeset function sets username AND name as required. In the example, the changeset is
changeset = User.changeset(User{username: “eric”},{}) but this misses the name field so this does not properly create a changeset with a set of changes but instead returns a changeset with errors. I think all you would need to do is add a name and this example would be fine.
2019-09-26
188
DEFER
On p.188 (of the PDF) the instruction is to create a param.ex file with a protocol implementation of to_param
I followed the instructions verbatim and nothing happens when I attempt to continue with the IEx instructions on p.189
Code:
github dot com/nelsonic/rumbl/tree/3a459389e26e55c32232acf3822f3b1156810a25
Happy to jump on a Skype/Zoom call to illustrate.
Elixir 1.9.0 (compiled with Erlang/OTP 22)
Phoenix v1.4.9
203
TYPO
“and assign the rest fo the topic to the video_id variable”
should be:
“and assign the rest of the topic to the video_id variable”
fo >> of
2019-09-25
212
TYPO
Grammar (missing word) in the following sentence:
“If an application needs change in the future, we can revisit this decision.”
could be:
“If an application needs to change in the future, we can revisit this decision.”
2019-09-25
241
ERROR
On page 241 we are advised to move the rumbl/assets/js to rumbl_umbrella/apps/rumbl_web/assets/
That’s fine, but then people also need to update the path to the phoenix and phoenix_html dependencies in apps/rumbl_web/assets/package.json from:
As Sam McDavid noted (see above) there are a number of other changes required to get the app running.
This is what I had to do:
First in the file `apps/rumbl_web/lib/rumbl_web/application.ex`, add `RumblWeb.Presence` to the list of supervised child processes, e.g:
`
children = [
RumblWeb.Endpoint,
RumblWeb.Presence
]
```
Then in the `apps/rumbl_web/lib/rumbl_web/channels/presence.ex` file, change:
```
use Phoenix.Presence,
otp_app: :rumbl,
pubsub_server: Rumbl.PubSub
```
to:
```
use Phoenix.Presence,
otp_app: :rumbl_web,
pubsub_server: RumblWeb.PubSub
```
Fully working app:
githubcom/nelsonic/rumbl/tree/25e68f6355c9f1610d0b9f45271f3d63e1b77686
2019-09-26
265
ERROR
While following the OTP chapter, after painstakingly inputting the code for info_sys/lib/info_sys/cache.change1.ex
When attempting to follow the iex instructions:
iex> alias InfoSys.Cache
iex> Cache.put(“one plus one?”, “two”)
have retraced steps and copied-pasted code from listings to ensure no PEBKAC.
Sadly, unable to fix. Code snapshot up to this point: gitio/fj7hX
Please help/fix. Thanks!
Elixir 1.9.0 (compiled with Erlang/OTP 22)
Phoenix v1.4.9
MacOS 10.14.6
2019-09-26
Thanks Nelson, I marked this as a duplicate of that one. Please see my reply there!
239
DEFER
You instruct the reader “We’re going to need three dependencies, :comeonin, :pbkdf2_elixir and :sweet_xml.” whereas the code listing does not contain `:comeonin` (nor do I think it needs to as it seems to be a transitive dependency through :pbkdf2_elixir). The code listing does contain sweet_xml - but we have not used this library up to this point in the book - so its a bit confusing for it to suddenly appear
2019-09-26
241
SUGGEST
there is no instruction to copy the css over; the styles we added before (video.css from pp 184-185) are minimal but they do exist so its weird to discard them now
2019-09-26
242
TYPO
When adding back the test speed-up config you have the listing as:
config :pbkdf2_elixir, :rounds, 1
whereas before it was
config :pbkdf2_elixir, rounds: 1
(which I understand to be equivalent to `config :pbkdf2_elixir, {:rounds, 1}` but not actually `config :pbkdf2_elixir, :rounds, 1` - I did not try the latter so maybe it also works)
2019-09-25
239
SUGGEST
expounding on #85674 - also the listing elides jason, which was in the default depset from the generator for me
I don’t believe we do any direct json parsing in rumbl (and I understand jason to already be a transitive dep of ecto_sql AND postgrex - so I’m unclear why its in the generator output to begin with) - but the text should maybe have an explicit note re: removing it - or the listing should retain it
2019-09-26
Jason is an optional dependency for both Ecto and Postgrex, so those dependencies should not bring it in. Maybe other dependencies are bringing Jason but it is best to be explicit and bring it in rather than depend on someone else doing it for us. Thanks!
80
ERROR
This code snippet is missing an alias:
iex> recompile()
iex> alias Rumbl.Repo
iex> for u <- Repo.all(User) do
…> Repo.update!(User.registration_changeset(u, %{password: “temppass”})) …> end
MISSING: alias Rumbl.Accounts.User
2019-09-25
This carries over inside an open iex session.
217
TYPO
The first line of the scheduleMessages function uses scheduleTimer instead of schedulerTimer:
On second paragraph, “UndefinedFunctionError” is spelled missing a c: “UndefiniedFuntionError”. Full text:
Before moving forward, let’s briefly review the error page. At the top the page
we get the exception name: UndefinedFuntionError.
2019-09-26
126
DEFER
The last paragraph on the page begins with “Importing Ecto.Query makes the Ecto query language available to us.”, and after a few more sentences describing Ecto.Query it says “We also import the Ecto.Query module and alias Repo and Category.”
That basically boils down to “Importing Ecto.Query. Also importing Ecto.Query and […]”, which is both confusing and redundant :)
2019-09-26
131
OK
The fourth bullet point says “When the select part is omitted, the whole struct is returned, as if we’d written select: u.”, but the query on this page (“Repo.one(from u in User, where: u.username == ^username)”) does not have a select part. The reader will have to go four pages back to find an example of using select.
2019-09-25
the text says we omit the select... e.g. it's the default.
26
SUGGEST
The text says “The router will call the world action on our controller, passing all of the information we need. We call the functions invoked by the router on our controller’s actions, but don’t get confused. They’re just functions.”
1) remove apostrophe on “controller’s”
2) Second sentence is confusingly worded. Consider revising to “We will refer to any functions that the router invokes on our controllers as ‘actions’, but don’t get confused.”
2019-09-25
27
TYPO
“Finally, since name: name is the last argument, of a function, we can omit the brackets.”
Stray comma, remove the second one.
2019-09-25
305
TYPO
> “In every case, render/1 is a pure function that takes socket.assigns as it’s lone argument.”
Should be `its`.
2019-09-26
307
TYPO
> That’s because under the hood, this LiveView is an GenServer!
Should be `a GenServer` instead of `an`.
2019-09-26
308
TYPO
“We’d have to estalish a separate route for each link and form.”
Should be `establish`.
2019-09-26
141
TYPO
“Along the way we’ll explore some of the the different ways you can use Ecto to retrieve data from the
database.”
2019-09-25
267
ERROR
The text states “Our struct has :score for storing relevance, :text to describe the result, :url for the URL it came from, and the :backend to use for the computation.”, but the struct in question (defined on the previous page) is defined like this:
defmodule Result do
defstruct score: 0, text: nil, backend: nil
end
That is, it does not have the URL field the text describes.
One uses :info_sys as the app name, the other one :rumbl. They need to have the same name for the code to work.
2019-09-26
Duplicate of #85794. Thanks!
142
ERROR
The example when inserting the “test” Category is wrong. The output has a field with the name: “hello”, it should be “test”.
2019-09-25
171
189
TYPO
The mix test command on pdf shows 9 tests, but should actually be 6. On the previous page, the number of tests is 2, and 4 were added, leading 6. This is annoying because I thought I missed something, but counting proved it not to be the case.
25
TYPO
The word “Function” in the exception “UndefinedFunctionError” was missing a letter “c”
210
ERROR
About programming the token in app.html.eex, the code needed to be added, namely:
"
"
Works only when accessing the server locally. If I try to access it thru another computer, I get an error ni Google Chrome: “GET localhost:4000/hs/app.js net::ERR_CONNECTION_REFUSED”
The code which works in other computers is:
“<script type=”text/javascript" src=“<%= Routes.static_path(@conn, ”/js/app.js“) %>”>
"
Which is exactly the code from before the modification
26
TYPO
The ebook the error complains:
undefined function: HelloWeb.HelloView.render/2
(module HelloWeb.HelloView is not available)
but in my terminal complains to:
` ` (UndefinedFunctionError) function HelloWeb.HelloView.render/2 is undefined (module HelloWeb.HelloView is not available)`
154
TYPO
There is “…having a hardcoded valid email and password…” in the first paragraph, but we using usernames instead of emails to identify the user. Also in the previous page test named “returns not found error with no matching user for email”, but again - usernames.
183
165
ERROR
In Part I, Chapter 8, the tests don’t seem to have been updated to reflect changes made progressively to the Multimedia context. One example is on this page for the use of `Multimedia.list_videos` .
Earlier, that function was already changed to use a `user` parameter to scope the video list by user. I’ve been changing my tests as I go along, to reflect that and other similar cases of filtering by user.
187
169
ERROR
In the “setup”, I needed to also assign “:current_user” to “nil”, not just implement “bypass_through”, since the pipeline doesn’t (yet) add that expected key to assigns:
The solution I suggested in a previous erratum for this page involved the missing key :current_user on conn.assigns. That solution changed the test, which is not DRY.
It seems better to change the RumblWeb.Auth plug’s “call” function to check the map for that key:
cond do
Map.has_key?(conn.assigns, :current_user) && conn.assigns.current_user ->
conn
… etc.
189
173
ERROR
Variable “owner” is unused in the last test (line 25 in listing)
163
SUGGEST
I could be just me, but I had great difficulty getting through this code. This forum post describes my prob. Perhaps it could be made clearer, I don’t know. The two “setup do” implementations proved to be an unsurmountable issue. It might have been assumed that I would only use one, but I did not understand that I should have only used one “setup do”. After only using one “setup do” I am running 4 tests instead of the book’s indication of 5.
The requested URL /titles/phoenix14/code/relationships/listings/rumbl/priv/repo/migratio ƒ 80513030504_add_category_id_to_video.change1.exs was not found on this server.
Apache/2.4.7 (Ubuntu) Server at media-origin.pragprog.com Port 80
99
ERROR
“By passing the :method option to link, Phoenix generates a form tag instead of an anchor tag. Links without a specified HTTP method will default to GET, and Phoenix will render a simple link.”
This doesn’t seem to be case anymore since phoenix_html PR#157.
152
TYPO
In a synopsis of 3 separate failing tests, the same test is listed twice (testing a password that’s too short). The username uniqueness test isn’t mentioned
147
ERROR
In the part of the page:
Whether you knew it or not, Phoenix has already been generating default tests for you, such as test/rumbl_web/controllers/video_controller_test.exs, test/rumbl/accounts/, and test/rumbl/multimedia/.
My test directory don’t generated automatically the folder accounts and multimedia.
My test directory:
test
├── rumbl
│ └── multimedia_test.exs
├── rumbl_web
│ ├── channels
│ ├── controllers
│ │ ├── page_controller_test.exs
│ │ └── video_controller_test.exs
│ └── views
│ ├── error_view_test.exs
│ ├── layout_view_test.exs
│ └── page_view_test.exs
├── support
│ ├── channel_case.ex
│ ├── conn_case.ex
│ └── data_case.ex
└── test_helper.exs
148
ERROR
For take the exactly same errors like: 3 tests, 1 failure.
It was needed to delete the files: video_controller_test.exs and multimedia_test.exs.
166
ERROR
The link for download the source code redirects to the first Programming Phoenix book and not to the actual version 1.4 of the book.
So the correct link is:
pragprog.com/titles/phoenix14/source_code
124
TYPO
Typo in iex sample such that output doesn’t match input:
warning: function Rumbl.Accounts.User.registration_changeset/2 is undefined or private. Did you mean one of:
* register_changeset/2
As the error describes, we declared a function called register_changeset/2 in the Rumbl.Accounts.User module, but are trying to call Rumbl.Accounts.User.registration_changeset/2.
Great book so far, thanks.
223
ERROR
The private function on pg 223 for the auth controller assigns the token with a key :user_token. However, where the token is used on the client side (assets/js/socket.js) the parameter expects a userToken with a key :token. Updating the JS to use :user_token so it matches the auth controller corrects a failure in the browser console because of an unknown token.
47
ERROR
At page 47, I run into a confusing part:
Excerpt from the page
With our user in place, let’s define our Accounts context. We will add a couple
of functions which will allow user account fetching. Let’s create a new file in
lib/rumbl/accounts.ex and key this in:
controllers_views_templates/listings/rumbl/lib/rumbl/accounts.ex
To this
def list_users do
[%User{id: “1”, name: “Jose”, username: “josevalim”},
%User{id: “2”, name: “Bruce”, username: “redrapids”},
%User{id: “3”, name: “Chris”, username: “chrismccord”}]
end
Elixir can use multiple maps only if they are enclosed in a list like the above code.
For better context search on google for Solved:Possible errata in programming phoenix 1.4 version p1.0 pdf
202
TYPO
Maybe is the version different that I use but the log is different on my server output logs for this:
[info] CONNECTED TO RumblWeb.UserSocket in 216µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Connect Info: %{}
Parameters: %{“token” => “undefined”, “vsn” => “2.0.0”}
[info] JOINED videos:2 in 58µs
Parameters: %{}
172
SUGGEST
Page 172 contains copy regarding the length of time it takes to run the auth tests. I ran into slow tests by page 156 and was wondering if I’d screwed something up.
I suggest pulling forward the config rounds to 1 from page 172 to page 156 OR correct the test output at the bottom of page 156 (and elsewhere) to show ‘Finished in 6.3 seconds’
206
ERROR
When I try to do an Annotation I get this error on console:
TypeError: msgContainer is null
I copy and paste the cody and the error continues..
for access to try:
gitlab.com/romenigld/programming-phoenix-1.4/commit/893664f9cd90bee2548b7a6fb3fbea89b413c93f
206
ERROR
Sorry it was an error of mine rather use id on msg-container I put class.
And fixed when I change for the correct id tag.
The previous mistake was my mistake.
AFAIK there’s no guarantee that the rows will be returned in any specific order. Fails on my machine (unless I’m doing something wrong).
238
SUGGEST
I’m using the Phoenix version Phoenix v1.4.10 and the ‘Copying the Web Source Files’ it wasn’t necessary to do. All was in the place.
238
SUGGEST
I do a mistake, sorry. It needs to copy!
253
239
SUGGEST
$ mix test
This command fails as the config/test.ex file was not updated, some users may not have postgres as a users.
300
287
SUGGEST
Instead of loading the stubbed HTTP client in ```test_helper.exs, I’d suggest adding it to test/support/http_client.ex and adding the test/support to elixirc_paths. This way running tests from apps/rumbl_web would work as well.
167
ERROR
The code doesn’t run as written until the setup function is added. This must happen later in the book.
The tests kept failing in the authenticate_user function.
I saw something similar where you add the login_as: as part of the setup. The tests don’t run until the describe is added later in the text. I spent some time trying to figure out why those tests wouldn’t run, then you added the describe and the @tag. Also, the tests on page 163 change radically later in the text.
320
307
SUGGEST
The page ends with “Typically, the handle_event will update the state in some way, but it doesn’t have to. Let’s take a look at a third use case, command-line completion.” but the next one continues with the “counter” example. I think the last sentence is misplaced.
L4557
TYPO
In the “Setting Up Category Seed Data” section, a sample IEx session executes this command:
```elixir
Rumbl.Repo.insert! %Rumbl.Multimedia.Category{name: “Test”}
```
This book shows the following return value:
```elixir
%Rumbl.Multimedia.Category{ meta: #Ecto.Schema.Metadata<:loaded, “categories”>,
id: 1, inserted_at: ~N[2019-05-19 13:06:12],
name: “hello”,
updated_at: ~N[2019-05-19 13:06:12]
}
```
You’ll notice that the `name` in the return value is “hello”. It should be
“Test” since that is what was passed in.
293
TYPO
In the parte before to test has:
“Then we assert the socket has a user_id assigned and the join reply contains the previously creatrd annotations.”
First:
There in the final of the paragrapg has a gramaticall error in the word ‘creatrd’.
Second:
So the assert which really is doing is with the video_id.
assert socket.assigns.video_id == vid.id
And when I try to do the test it complains and error:
21:11:37.405 [error] Postgrex.Protocol (#PID<0.305.0>) disconnected: (DBConnection.ConnectionError) owner #PID<0.373.0> exited
Client #PID<0.376.0> is still using a connection from owner at location:
Now, change your show.html.eex
template to render it:
Showing User
<%= render “user.html”, user: @user %>
it must be :
<%= render “user.html”, user: user %>
153
TYPO
> “We start by defining a new describe block on line 4 which…”
This and all following line numbers are incorrect.
> test “returns not found error with no matching user for email” do
“email” should be “username”, also in the paragraph that follows.
282
ERROR
IMHO the 4th unit test which stops and restarts the Infosys.Cache interferes with the other 3 unit tests of the “cache_test.exs” file.
I guess the order the tests are executed is random, especially because “asyn: true” is set at the beginning.
Therefore, killing the cache OTP process could lead to race conditions for the other 3 test cases (the cache could die while some other tests is using it), or am i am missing something?
172
ERROR
At this point there are only 6 tests in the file, but the book states on page 172:
"
Now let’s run our new tests:
$ mix test test/rumbl_web/controllers/auth_test.exs
………
Finished in 1.9 seconds
9 tests, 0 failures
"
63
TYPO
not able to launch for …/users/new to get the desired output. Getting error message
[debug] (Ecto.CastError) expected params to be a :map, got: `:empty`
63
TYPO
My earlier entry #86163
actually you need to use %{} in place of :empty in the default value for params in definition of changeset/2 in the web/model/user.ex
has a bug, since :show is before :new if you go to /users/new it will route to the show controller with an id of “new” which both makes the new page inaccessible and generates a very confusing error. It needs to change to:
Now /users/new will route to the new controller instead.
23
TYPO
The output from mix phx.new is shown as:
Fetch and install dependencies? [Yn] y
running mix deps.get
running mix deps.compile
…
$ cd hello
$ cd assets
$ npm install
…
$ cd ..
The newer versions of phx.new automatically do the npm install for you, you don’t have to manually type it in. The output shown from a later version of phx.new on page 44 is correct, it shows the npm install command automatically being run.
xv
TYPO
Text: “OTP ‘GenServer‘s directly from the Elixir environment”
Not sure what’s with the left apostrophes. Was that meant to be backticks like `GenServers`?
205
190
ERROR
As the code for Permalink is presented, cast(“–1”) will return :error while cast(–1) will return {:ok, –1}. I doubt this is the expected behaviour. Suggestion is to add a guard check for integer > 0 to the relevant function definition:
def cast(integer) when is_integer(integer) and integer > 0 do
{:ok, integer}
end
26
TYPO
If I’m understanding it correctly, the sentence, “We call the functions invoked by the router on our controller’s actions, but don’t get confused,” should read, “We call the functions invoked by the router on our controllers ‘actions’, but don’t get confused.” This is a pernicious typo because the printed version is grammatically correct but technically incorrect (again, if I’m understanding its intention correctly).
144
128
TYPO
double “in” :
“will go in in contexts”
304
TYPO
“Now, you can get a better look at how we’ll encorporate changing state in the LiveView”
“encorporate” should be “incorporate”
113
SUGGEST
“We need to associate the video with the current user’s session” -> “We need to associate the video with the current session’s user”
137
SUGGEST
“changeset error messages: Beautiful error messages for the consumption of humans.” This is technically ambiguous: it may indicate error messages such as “Please do not eat the humans.” How about “for consumption by humans”?
147
ERROR
“test/rumbl/accounts/” and “test/rumbl/multimedia/” (two mentions in the same paragraph, the second asking the reader to delete them):
these directories do not exist. They were also not mentioned in the console output shown in Using Generators, p. 103, when other files such as multimedia_test.exs were created.
173
ERROR
Remove line 25 of listing: “owner = %Rumbl.Accounts.User{}”.
“owner” is unused, so this line generates a warning.
182
SUGGEST
“That way, external dependencies are never imported and available on the global JavaScript scope…”. Ambiguous: “are never imported nor available” or “are never imported and are available”?
182
TYPO
“you can add the watch option"> ”you can add the —watch option" [double dash]
186
SUGGEST
The text appears contradictory on whether slugs can change after creation: “The whole premise of a slug is that you can automatically generate a permanent field from other fields, some of which may be updateable. … If a change is made to the title, we build a slug based on the new title…” The code resolves the contradiction by including a permanent ID in the slug before the changeable title, which is ignored. News-oriented web sites that readers may be familiar with often base the slug on the original title with no numeric ID, use the full slug for lookups, and don’t change it, so explaining the differing approach in the text could avoid confusion.
215
TYPO
The code in “channels/listings/rumbl/assets/js/video.change6.js” uses “this.scheduleTimer” on one line but “this.schedulerTimer” on the next line.
223
SUGGEST
“Later, as Phoenix improves, we’ll show a browser icon for browser tabs…”: Does this refer to an upcoming Phoenix feature, and if so what? Or does it mean to say Rumbl, referring to a feature that could be written to support a future mobile client implementation?
257
SUGGEST
Minor inconsistency, which may or may not be intentional: One of the two start_link calls uses parens, while the other doesn’t.
287
ERROR
testing_otp/listings/rumbl_umbrella/apps/info_sys/test/backends/wolfram_test.exs
In test “no query results reports an empty list”, append “= []” to the assert line.
Request: POST /sessions
(exit) an exception was raised:
(FunctionClauseError) no function clause matching in String.split/3
(elixir) lib/string.ex:407: String.split(nil, “$”, [trim: true])
(pbkdf2_elixir) lib/pbkdf2.ex:109: Pbkdf2.verify_pass/2
(phxcodes) lib/phxcodes/accounts.ex:24: Phxcodes.Accounts.authenticate_by_username_and_pass/2
(phxcodes) lib/phxcodes_web/controllers/session_controller.ex:9: PhxcodesWeb.SessionController.create/2
(phxcodes) lib/phxcodes_web/controllers/session_controller.ex:1: PhxcodesWeb.SessionController.action/2
(phxcodes) lib/phxcodes_web/controllers/session_controller.ex:1: PhxcodesWeb.SessionController.phoenix_controller_pipeline/2
It Happened when after creating a new user and logged in, i tried to log out et log in again >>>>
the message displayed is :
"
FunctionClauseError at POST /sessions
no function clause matching in String.split/3
"
139
TYPO
‘New User’ view in the book has 4 fields.
I think that this view has 3 fields.
Thanks.
281
TYPO
The book shows ‘1 test, 0 failures’.
I think that ‘2 tests, 0 failures’ is correct.
172
TYPO
The book shows ‘9 tests, 0 failures’.
I think that ‘6 tests, 0 failures’ is correct.
293
TYPO
The book shows “Then we asset the socket has a user_id assigned and the join reply contains the previously ‘creatrd’ annotations”.
I think that ‘creatrd’ may be ‘created’.
141
125
TYPO
Typo on “behaviour” in the before last sentence “The downside is that the upsert behavour is often database specific, so make sure to explore the different options available to your database of choice.”
139
TYPO
The screenshot does not reflect the current state of the code as there’s no email field.
153
SUGGEST
Seeing the accounts_test.ex execution time, I think the book omitted to describe how to speed up password hashing, something like :
In config/test.ex
config :pbkdf2_elixir, :rounds, 1
62
ERROR
The link to Ecto.Migration API in the footnote is wrong. It should be “/ecto_sql/Ecto.Migration.html” instead of “ecto/Ecto.Migration.html”.
96
ERROR
“[…] anyone would be able to find whether an email is registered on the website.” should read “[…] anyone would be able to find whether a username is registered on the website.” since usernames and not emails are used to log in.
Ch.4
TYPO
“When we created our application, Phoenix generated an Ecto repository, called Rumble.Repo”
Should be Rumbl without the ‘e’.
I’m on Kindle for Mac, and it is 17% of the way through, location is 1976 of 12423, not sure what page number exactly, hope that helps!
188
SUGGEST
We really need to generate slugs for existing items in the db, e.g. in the migration
Ch.7
TYPO
“The downside is that the upsert behavour…”
I realize behavior is spelled differently in the UK/English etc, but I believe this should either be ‘behavior’ or ‘behaviour’, it seems to be missing the ‘i’.
I am on Kindle for Mac, so it’s hard to say the exact location, but it says it’s 38%, Location 4618 of 12423.
Ch.7
TYPO
Again, on Kindle for Mac so exact location is tough but it’s at 39%, or location 4739 of 12423.
“Complex interactions, such as those between our multimedia and users, will go in in…”
Duplicated the word “in”.
80
ERROR
“Then, our function delegates to the put_pass_hash function to compute and store the user hash in the database, like this:”
I think this part is not precise and for me it was misleading until I read the contents of that function.
What I think this part should say is:
“Then, our function delegates to the put_pass_hash function to compute and store the user hash in the changeset, like this:”
94
SUGGEST
In the first code listing on this page there is a call to ````Pbkdf2.no_user_verify() to prevent timing attacks.
As documentation of this function says: “This function is only useful if it is used as part of a policy of hiding usernames.”.
Up to this point usernames were not directly exposed in the app, however the new function authenticate_by_username_and_pass/2 returns different response for existing username (:unauthorized) and for not existing (:not_found).
Therefore existence of given username is exposed. Maybe function should respond with the same error for both cases?
205
ERROR
Though it doesn’t seem to impact the running of the app or the code, after adding the Permalink module, iex gives a couple of behaviour-related warnings:
warning: function embed_as/1 required by behaviour Ecto.Type is not implemented (in module Rumbl.Multimedia.Permalink)
lib/rumbl/multimedia/permalink.ex:1: Rumbl.Multimedia.Permalink (module)
warning: function equal?/2 required by behaviour Ecto.Type is not implemented (in module Rumbl.Multimedia.Permalink)
lib/rumbl/multimedia/permalink.ex:1: Rumbl.Multimedia.Permalink (module)
188
172
SUGGEST
Page 172 suggests adding ‘config :pbkdf2_elixir, :rounds, 1’ to ‘rumbl/config/test.exs’ to speed up the test suite. This should be suggested somewhere near the beginning of the ‘Testing MVC’ chapter.
The very first test file that readers get to write (rumbl/test/rumbl/accounts_test.exs) involves creating a user record that goes through the slow hashing rounds. For me, running the 5 test examples in the file took around 3 seconds without the pbkdf2_elixir rounds config, but the book shows ‘Finished in 0.1 seconds’. 0.1 seconds is obviously the result of adding the rounds config, but the book never mentions that config until page 172.
Some readers might not notice the discrepancy and just suffer from slow tests until they get to the page that introduces the config, or some might notice the difference early and spend their time trying to figure out why their tests are not finishing in 0.1 seconds.
65
SUGGEST
Around this page you introduce a pattern in the code samples “path/accounts.change1.ex” and it is not clear if the reader should create this new file or update the existing accounts.ex file. On this page the example is updating the Accounts context which it feels strange to introduce a new file or rename the accounts.ex file. I ultimately just updated the accounts.ex file but this naming convention is not explained. Also on this page you are missing the accounts folder in the path.