Programming Phoenix, Ch. 5, Generated code does not match book

Hi all,

I’m going through the book (ebook) and I’m currently in Chapter 5, at the section titled “In-context Relationships.”

Following the book, it tells me to use generators to create a context within another context. More specifically, the Credential context within the Accounts context.

This is what the book tells me to type into my console:

$ mix​​ ​​phx.gen.context​​ ​​Accounts​​ ​​Credential​​ ​​credentials​​ ​​\​
​ 	​email:string:unique​​ ​​password_hash:string​​ ​​user_id:references:users​

And this is what the book says the output should be:

 1 You are generating into an existing context.
 2 The Rumbl.Accounts context currently has 8 functions and 2 files in its directory.
​ 3 	
​ 4	  * It's ok to have multiple resources in the same context as
​ 5	    long as they are closely related
​ 6	  * If they are not closely related, another context probably works better
​ 7	
​ 8	If you are not sure, prefer a new context over adding to the existing one.
​ 9	
​10 	
​11	Would you like proceed? [Y/n] y
​12 	* creating lib/rumbl/accounts/credential.ex
13	* creating priv/repo/migrations/20180410050016_create_credentials.exs
​14 	* injecting lib/rumbl/accounts/accounts.ex
​15 	* creating test/rumbl/accounts/accounts_test.exs
16​ 	* injecting test/rumbl/accounts/accounts_test.exs

Pay particular attention to lines 1-11 and 14 in the output. Those two lines are not what I see in the output of my console. Here’s what I see:

A * creating lib/rumbl/accounts/credential.ex
B * creating priv/repo/migrations/20200527061947_create_credentials.exs
C * creating lib/rumbl/accounts.ex
D * injecting lib/rumbl/accounts.ex
E * creating test/rumbl/accounts_test.exs
F * injecting test/rumbl/accounts_test.exs

There was no warning about generating into an existing context, and as you can see, it created a new context accounts.ex in the directory above (lines C and D), rather than injecting code into the existing file in lib/rumbl/accounts/accounts.ex.

For good measure, I ran $ mix ecto.migrate, and got this in response:

== Compilation error in file lib/rumbl/accounts/accounts.ex ==
** (CompileError) lib/rumbl/accounts/accounts.ex:1: cannot define module Rumbl.Accounts because it is currently being defined in lib/rumbl/accounts.ex:1
    (stdlib 3.13) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir 1.10.3) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

Any ideas? I’d appreciate any help.

Thanks!

1 Like

The generator expects that your Accounts context, if existing, would be in the lib/rumbl/accounts.ex file. Now, as the file did not exist, the generator assumed that you were creating a new context, and created the file, defining a Rumbl.Accounts module.

What you expected is that the generator would detect that a Rumbl.Accounts module was already defined in another file (lib/rumbl/accounts/accounts.ex) but I do not think that the generator is such sophisticated.

The generator follows the file naming convention for modules, and if you followed this convention, lib/rumbl/accounts/accounts.ex would contain the Rumbl.Accounts.Accounts module, which is not the case.

Now you have two files defining a Rumb.Accounts module, and that makes the compiler angry, so it tells you : lib/rumbl/accounts/accounts.ex:1: cannot define module Rumbl.Accounts because it is currently being defined in lib/rumbl/accounts.ex:1

So now you should open those two files and merge their contents into a single file, preferably lib/rumbl/accounts.ex if you plan to use the generators again for this context.

Thanks! So is this is an errata in the book? Not sure how they got the generator to work that way. You can see in Line 14 of their output, it injected into lib/rumbl/accounts/accounts.ex

It kind of puts into question how much I can rely on this book teaching me the right things…

Well all I said was from my memory so I may have mixed up things. Maybe I inverted the two file paths. Or the book is for an older version of Phoenix.

But in either case, the generator created lib/rumbl/accounts.ex, which is not what the book tells you because it may be outdated, but anyway that works. Now can you remember how the lib/rumbl/accounts/accounts.ex file was created ?

All good. Thanks for the help!

re: how /lib/rumbl/accounts/accounts.ex was created, the book gave instructions to create that file manually in an earlier chapter (Chapter 3, Controllers).

1 Like

Ok then I guess the file/module mapping strategy of the generators has changed since the publication of the book, or it is indeed an erratum.