Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to mix phx.gen.html --no-context (without Context) #3832

Closed
nelsonic opened this issue May 11, 2020 · 2 comments
Closed

Unable to mix phx.gen.html --no-context (without Context) #3832

nelsonic opened this issue May 11, 2020 · 2 comments

Comments

@nelsonic
Copy link

nelsonic commented May 11, 2020

Hi! 👋

Trying to run the mix phx.gen.html with the --no-context and --no-schema flags because I only want to create a controller, view, templates and tests for a new resource.
As per the docs: https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Html.html#module-customising-the-context-schema-tables-and-migrations

Note totally agree that there is definitely a use-case for Contexts in larger projects, but in a small project like the tutorial/example I'm building it just adds complexity without any benefit.

The command I've have attempted to run is:

mix phx.gen.html Quotes quotes author:string text:string --no-context --no-schema

But see the following error:

** (Mix) Expected the schema, "quotes", to be a valid module name

mix phx.gen.html, phx.gen.json, phx.gen.live, and phx.gen.context
expect a context module name, followed by singular and plural names
of the generated resource, ending with any number of attributes.
For example:

    mix phx.gen.html Accounts User users name:string
    mix phx.gen.json Accounts User users name:string
    mix phx.gen.live Accounts User users name:string
    mix phx.gen.context Accounts User users name:string

The context serves as the API boundary for the given resource.
Multiple resources may belong to a context and a resource may be
split over distinct contexts (such as Accounts.User and Payments.User).

The error message and examples suggest we must include a Context in as the first argument to mix phx.gen.html regardless of using the --no-context flag.

So added a dummy context to the mix phx.gen.html command:

mix phx.gen.html Ctx Quotes quotes author:string text:string --no-context --no-schema

And that appears to work in that we see the following output:

* creating lib/app_web/controllers/quotes_controller.ex
* creating lib/app_web/templates/quotes/edit.html.eex
* creating lib/app_web/templates/quotes/form.html.eex
* creating lib/app_web/templates/quotes/index.html.eex
* creating lib/app_web/templates/quotes/new.html.eex
* creating lib/app_web/templates/quotes/show.html.eex
* creating lib/app_web/views/quotes_view.ex
* creating test/app_web/controllers/quotes_controller_test.exs

Add the resource to your browser scope in lib/app_web/router.ex:

    resources "/quotes", QuotesController

e.g: dwyl/phoenix-content-negotiation-tutorial@9a37b21

But when attempting to run the tests immediately after running the mix phx.gen.html command,
we see a compilation error:

== Compilation error in file lib/app_web/controllers/quotes_controller.ex ==
** (CompileError) lib/app_web/controllers/quotes_controller.ex:13: App.Ctx.Quotes.__struct__/1 is undefined, cannot expand struct App.Ctx.Quotes. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
    (stdlib 3.11.2) lists.erl:1354: :lists.mapfoldl/3

The QuotesController generated by the mix phx.gen.html command is attempting to alias App.Ctx.Quotes on line 5 of the file:
https://github.com/dwyl/phoenix-content-negotiation-tutorial/blob/6f067cf8923e4fd481e3f7fc1a87a9c3d602a87d/lib/app_web/controllers/quotes_controller.ex#L4-L5

This context does not exist (and we don't want it to).

Expected behavior

We would expect that running mix phx.gen.html with the --no-context flag to create a controller without a context.

Actual behavior

The mix phx.gen.html creates a controller that attempts to alias a module that does not exist.

Check

Reading the tests for --no-context:

test "with --no-context skips context and schema file generation", config do
in_tmp_project config.test, fn ->
Gen.Html.run(~w(Blog Comment comments title:string --no-context))
refute_file "lib/phoenix/blog.ex"
refute_file "lib/phoenix/blog/comment.ex"

We see that it merely refutes the existence of the "lib/phoenix/blog.ex" file (the Context in the test case) but it does not make any assertion as the content of the comments controller.

Feedback

I feel that the --no-context flag is insufficiently documented.
And consider the creation of a controller full of references to Ctx. (context namespace) to be a bug (or at least unexpected/undesirable behaviour). Running the mix phx.gen.* should not create code that does not compile.

If it's not possible to create a controller using mix phx.gen.* without a Context then the --no-context flag is miss-leading.

Environment

  • Elixir version (elixir -v): Elixir 1.10.1 (compiled with Erlang/OTP 22)
  • Phoenix version (mix deps): Phoenix v1.5.1 (mix phx.new -v)
  • NodeJS version (node -v): v12.16.2
  • NPM version (npm -v): 6.14.4
  • Operating system: OSX 10.15.4

Steps to Reproduce

Create a basic Phoenix App e.g:

mix phx.new app --no-ecto --no-webpack

Run the tests to confirm everything works.

mix test

You should see the following output in your terminal:

Generated app app
...

Finished in 0.02 seconds
3 tests, 0 failures

Attempt to create a Controller, View and Templates for a "Quotes" Resource without a Context:

mix phx.gen.html Ctx Quotes quotes author:string text:string --no-context --no-schema

That will create the files and it appears to all be good.
But now attempt to run the tests:

mix test

You will see a compilation error:

== Compilation error in file lib/app_web/controllers/quotes_controller.ex ==
** (CompileError) lib/app_web/controllers/quotes_controller.ex:13: App.Ctx.Quotes.__struct__/1 is undefined, cannot expand struct App.Ctx.Quotes. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
    (stdlib 3.11.2) lists.erl:1354: :lists.mapfoldl/3
nelsonic referenced this issue in dwyl/phoenix-content-negotiation-tutorial May 11, 2020
@chrismccord
Copy link
Member

Per the docs:

In some cases, you may wish to bootstrap HTML templates, controllers, and controller tests, but leave internal implementation of the context or schema to yourself.

In this case, we leave the context and schema implementations up to you, but it is still up to you to define them. The generators are first and foremost learning tools, so we have no plans to support a set of generators that puts the code directly in the controller, but you are free to write an external library that fit your generator needs. Thanks!

@nelsonic
Copy link
Author

Thanks for clarifying @chrismccord 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants