Programming Phoenix (Pragprog)

What typically happens is that you get issued a coupon to buy the physical book at a discount.

For example when “Programming Ecto” went to print a coupon was issued (to the account) for purchasing the paper book for $14.95 (instead of $37.95).

Thank you for the tips

It was actually a $14.95 discount, so the book was $23.

Thank you for the correction - yes it is “Save $14.95”.

In the case of “Programming Ecto” is was issued 2019-04-09 and expires 2020-04-11.

FYI: Last couple of years they had a “Christmas in July” 40% off sale for ebooks, screencasts, and audio books.

1 Like

B9 is now out :023:

Content-complete and heading to copy edit and indexing.


3 posts were split to a new topic: What is a Phoenix Plug?

B10.0 released

Copy edit and indexing are complete. Now it’s on to layout and the printer.


I ordered it on Amazon 2 years ago :smiley: Yesterday I got an email that it was delayed another time :smiley:


That’s the reason I read web dev books in soft.

I can’t read more than two pages on the screen without getting tired or extremely stressed. I hoped for color e-ink displays in ebook readers but seems like the market just doesn’t care. I have a lot of ebooks laying around which I don’t read because of this. If a technical book is available in print, I buy that instead of the ebook.


Have you tried the new Oasis? I love mine:


But that is still no color e-ink. I can’t imagine to read tons of source code and screenshots in grayscale.

1 Like

Does anyone know where I can find an up to date version of the source code?

I bought this book from the PragProg website and downloaded the source code from there too. Unfortunately, the code blocks in the book do not match up with provided code, looks like it’s for an old version.

Edit: Made it all the way to chapter 9 without realising the file paths above the code blocks are links to the source :roll_eyes:


Hello everyone,

I don’t know if this is the right place to question about some code of the book so if Im at the wrong place just let me know. here I go

At chapter 4 (Esto), user struct is modified into this

“defmodule​ Rumbl.Accounts.User ​do​
​ ​use​ Ecto.Schema
​ ​import​ Ecto.Changeset

​ schema ​"​​users"​ ​do​
​ field ​:name​, ​:string​
​ field ​:username​, ​:string​

​ timestamps()
​ ​end​
​ ​end​”

then a code is generated with the sentence ​​-> mix​​ ​​ecto.gen.migration​​ ​​create_users​

The file generated in my case was almost empty
defmodule Rumbl.Repo.Migrations.CreateUsers do
use Ecto.Migration

def change do


My question is, was the code well generated? and is my duty edit it and make it into this(just as appears in the book)

defmodule Rumbl.Repo.Migrations.CreateUsers do
use Ecto.Migration

def change do
create table(:users) do
add :name, :string
add :username, :string
add :password_hash, :string


create unique_index(:users, [:username])


I still don’t get if the sentence -> mix​​ ​​ecto.gen.migration​​ ​​create_users​ really generate the migration file with the add sentences and timestamp or if it just creates the skeleton just like it did in my case.

Thanks in advance to anyone and I hope you can give me a hand. I’m really excited reading this book.


it is your duty to fill out the migration. It seems strange to have to write almost the same code twice, but soon you will start writing schema that don’t look like migrations (for example containing UX elements), or multiple different schemas for the same table (one for business logic and one for UX) etc.

Also generally speaking, in phoenix, except for the really low level stuff like handling http connections, parsing headers, etc, if you don’t see the code that does something, it’s not there. The macros do sprinkle magic in there, but the magic that gets sprinkled is more or less “opinionated code organization”. It took me a while to understand this and learn how to follow the macros to find the things, but I spent a lot of angst worrying that it was like RoR.

I’m certainly no expert on Phoenix, but I did go through that chapter recently.

My understanding is that mix​​ ​​ecto.gen.migration​​ ​​create_users will only generate the skeleton of the migration. You would then fill out the schema section and run mix ecto.migrate to apply the changes to the database.

I believe the authors’ intentions were to show how to not rely exclusively on generators, which are later presented in Chapter 6. For instance, one command seen later on mix phx.gen.html Multimedia Video videos user_id:references:users url:string title:string description: test generates several files, including a more fleshed out migration based on the inputs provided for the command.

Hopefully I didn’t butcher any explanation too badly, but that should be the gist… Hope that helps!

1 Like

Thanks for the explanation. I just wanted to be sure and follow to next charters with solid foundations (trying it at least]

Thanks for your reply it really helped me. As I wrote before I’m trying to go further in the books but with “solid” foundations and really understand the frameworks and the philosophy.

Thanks again for your help

1 Like

Hello again guys,

This time I bring some questions regarding the charter 5 (authentication) I hope you could help to figure then out.

  1. Is the changes function (created at chapter 4) being used (called) in the registration_changeset function? if that’s true is the function cast being invoked 2 times? would be better (for performance at very low low level) just create registration_changeset function without using the changeset function and obviously putting its logic in the registration_changeset function?

  2. There is a point in the book where are updated all the users already presents in DB adding a password. why if all the passwords are being created using the same key the password_hash stored in DB is different in all cases/users?

  3. is correct the password_hash store in DB would be like this ‘$pbkdf2-sha512$160000$p1reFOXMlI1K1qplSHlNNg$/TLJ6ffDICFlwcvFkc0awRBkJXsV6d/DUYoy5QEv/PUAVLgM1kdt2qZQDhzoCck9pEm.gFeLltfx04qSi7SYlg’? including $pbkdf2-sha512$160000$ at the beginning of each one

  4. The final implementation of create function on user_controller

    #antes del cambio
    #case Accounts.create_user(user_params) do
    case Accounts.register_user(user_params) do
      {:ok, user} ->
        |> RumblWeb.Auth.login(user)
        |> put_flash(:info, "#{} created!")
        |> redirect(to: Routes.user_path(conn, :index))

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset)
type or paste code here

throws a warning calling RumblWeb.Auth.login function saying

is undefined or private

  1. Supposed I have several controllers and all of them needs user authentication, what would be the best way to use the authentication plug cross controller? in the route pipeline? How?

  2. Why the authentication plug was developed in the controller folder because as far as I understood is not a controller, in fact wonder why the login function was located in that module instead of being located anywhere else, maybe because it fits better in the controller layer?

Sorry for being so annoying, and thanks in advance to all of you

Here’s my take on some of the questions. Again, keep in mind I am no expert in Phoenix:

  1. I’m not knowledgeable about the performance implications, but this proposed approach could get messy with excessive code duplication once functionality beyond the book is introduced. For instance, if you wanted to add a “change password” functionality then you’d duplicate the contents of changeset again.

  2. In this situation, the same passwords are being used across all accounts… so if we were to hash just the password itself, we should indeed get the same hashes for each user. However, in addition to the password, we also add a random salt (of a consistent length) to the password before hashing. This salt is what causes a different result for each entry. Salting is a standard technique and can help guard against attacks like rainbow tables.

  3. I believe this is fine and correct. From what I gather, the technique used to generate the password is simply being prepended along with the number of iterations. This is not uncommon and can be useful if you ever need to change how you process a password in the future.

  4. I did not get this warning earlier this week… could there be a typo somewhere causing it?

  5. I’m not sure if there is a better place than the route pipeline for the Auth plug, but it seems to generalize well in that location later on in the book.

  6. I don’t have enough exposure to Phoenix to provide advice here.