Repository: phoenixframework/phoenix
Pull request #3699 (2020-03-07 18:22:17)

Generate web view_helpers/0 when html not selected
This fixes a compilation error in the generated {app_name}_web.ex file:

```
== Compilation error in file lib/demo_web.ex ==
** (CompileError) lib/demo_web.ex:40: undefined function view_helpers/0
    (elixir 1.10.2) src/elixir_locals.erl:114: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
    (stdlib 3.9) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir 1.10.2) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
```

~The view_helpers/0 function is not generated in the web context if "--no-html" is used, so we need to check for html before generating the line to invoke view_helpers().~

Some of the imports/aliases in `view_helpers/0` are used even without html. This PR moves the html conditional into the function so that `view_helpers()` can be invoked in all cases.

## Examples

`mix phx.new demo --no-html --no-gettext`

```elixir
  defp view_helpers do
    quote do
      import DemoWeb.ErrorHelpers
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```

`mix phx.new demo --no-html`

```elixir
  defp view_helpers do
    quote do
      import DemoWeb.ErrorHelpers
      import DemoWeb.Gettext
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```

`mix phx.new demo`

```elixir
  defp view_helpers do
    quote do
      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML

      import DemoWeb.ErrorHelpers
      import DemoWeb.Gettext
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```

`mix phx.new demo --live`

```elixir
  defp view_helpers do
    quote do
      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML

      # Import convenience functions for LiveView rendering
      import Phoenix.LiveView.Helpers

      import DemoWeb.ErrorHelpers
      import DemoWeb.Gettext
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```

`mix phx.new demo --umbrella --no-html --no-context`

```elixir
  defp view_helpers do
    quote do
      import DemoWeb.ErrorHelpers
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```

...

`mix phx.new demo --umbrella --live`

```elixir
  defp view_helpers do
    quote do
      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML

      # Import convenience functions for LiveView rendering
      import Phoenix.LiveView.Helpers

      import DemoWeb.ErrorHelpers
      import DemoWeb.Gettext
      alias DemoWeb.Router.Helpers, as: Routes
    end
  end
```




josevalim: Hi @mcrumm. I think the correct fix is actually to always generate view_helpers. That's because in there we have the router alias and the gettext import, that you may want to have even if not using HTML.
mcrumm: Good catch! I'll make the requisite changes.
mcrumm: @josevalim Ready for another look
josevalim: Great! can you change the test that uses `--no-html` to assert  that a `defp view_helpers` is generated? Thanks!

Patch:
diff --git a/installer/templates/phx_single/lib/app_name_web.ex b/installer/templates/phx_single/lib/app_name_web.ex
index 9bd73a420..4cad6b554 100644
--- a/installer/templates/phx_single/lib/app_name_web.ex
+++ b/installer/templates/phx_single/lib/app_name_web.ex
@@ -73,21 +73,21 @@ defmodule <%= web_namespace %> do
       use Phoenix.Channel<%= if gettext do %>
       import <%= web_namespace %>.Gettext<% end %>
     end
-  end<%= if html do %>
+  end
 
   defp view_helpers do
-    quote do
+    quote do<%= if html do %>
       # Use all HTML functionality (forms, tags, etc)
       use Phoenix.HTML<%= if live do %>
 
       # Import convenience functions for LiveView rendering
       import Phoenix.LiveView.Helpers<% end %>
-
+<% end %>
       import <%= web_namespace %>.ErrorHelpers<%= if gettext do %>
       import <%= web_namespace %>.Gettext<% end %>
       alias <%= web_namespace %>.Router.Helpers, as: Routes
     end
-  end<% end %>
+  end
 
   @doc """
   When used, dispatch to the appropriate controller/view/etc.
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
index 3d79339fd..aa662c08f 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
+++ b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
@@ -73,21 +73,21 @@ defmodule <%= web_namespace %> do
       use Phoenix.Channel<%= if gettext do %>
       import <%= web_namespace %>.Gettext<% end %>
     end
-  end<%= if html do %>
+  end
 
   defp view_helpers do
-    quote do
+    quote do<%= if html do %>
       # Use all HTML functionality (forms, tags, etc)
       use Phoenix.HTML<%= if live do %>
 
       # Import convenience functions for LiveView rendering
       import Phoenix.LiveView.Helpers<% end %>
-
+<% end %>
       import <%= web_namespace %>.ErrorHelpers<%= if gettext do %>
       import <%= web_namespace %>.Gettext<% end %>
       alias <%= web_namespace %>.Router.Helpers, as: Routes
     end
-  end<% end %>
+  end
 
   @doc """
   When used, dispatch to the appropriate controller/view/etc.


Test patch:
diff --git a/installer/test/phx_new_test.exs b/installer/test/phx_new_test.exs
index 8481ab35c..a886ac32f 100644
--- a/installer/test/phx_new_test.exs
+++ b/installer/test/phx_new_test.exs
@@ -250,6 +250,8 @@ defmodule Mix.Tasks.Phx.NewTest do
 
       assert_file "phx_blog/mix.exs", &refute(&1 =~ ~r":phoenix_html")
       assert_file "phx_blog/mix.exs", &refute(&1 =~ ~r":phoenix_live_reload")
+      assert_file "phx_blog/lib/phx_blog_web.ex",
+                  &assert(&1 =~ "defp view_helpers do")
       assert_file "phx_blog/lib/phx_blog_web/endpoint.ex",
                   &refute(&1 =~ ~r"Phoenix.LiveReloader")
       assert_file "phx_blog/lib/phx_blog_web/endpoint.ex",
diff --git a/installer/test/phx_new_umbrella_test.exs b/installer/test/phx_new_umbrella_test.exs
index 97787a23f..32bf39c83 100644
--- a/installer/test/phx_new_umbrella_test.exs
+++ b/installer/test/phx_new_umbrella_test.exs
@@ -264,6 +264,8 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
 
       assert_file web_path(@app, "mix.exs"), &refute(&1 =~ ~r":phoenix_html")
       assert_file web_path(@app, "mix.exs"), &refute(&1 =~ ~r":phoenix_live_reload")
+      assert_file web_path(@app, "lib/#{@app}_web.ex"),
+                  &assert(&1 =~ "defp view_helpers do")
       assert_file web_path(@app, "lib/#{@app}_web/endpoint.ex"),
                   &refute(&1 =~ ~r"Phoenix.LiveReloader")
       assert_file web_path(@app, "lib/#{@app}_web/endpoint.ex"),