Skip to content

Commit

Permalink
Conditionally generate child_spec with elixir >= 1.5. Closes phoenixf…
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismccord committed Jan 18, 2018
1 parent e8a0fc0 commit 2b4ecc4
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 18 deletions.
23 changes: 22 additions & 1 deletion installer/lib/phx_new/generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ defmodule Phx.New.Generator do
end

binding = [
elixir_version: elixir_version(),
app_name: project.app,
app_module: inspect(project.app_mod),
root_app_name: project.root_app,
Expand All @@ -127,11 +128,31 @@ defmodule Phx.New.Generator do
adapter_module: adapter_module,
adapter_config: adapter_config,
generators: nil_if_empty(project.generators ++ adapter_generators(adapter_config)),
namespaced?: namespaced?(project)]
namespaced?: namespaced?(project),
]

%Project{project | binding: binding}
end

def stub_elixir_version(vsn, func) do
if configured_version() do
raise RuntimeError, "race condition detected when trying to stub elixir version"
end

try do
Application.put_env(:phoenix, :installer_elixir_vsn, vsn)
func.()
after
Application.delete_env(:phoenix, :installer_elixir_vsn)
end
end

defp elixir_version do
configured_version() || System.version()
end

defp configured_version, do: Application.get_env(:phoenix, :installer_elixir_vsn)

defp namespaced?(project) do
Macro.camelize(project.app) != inspect(project.app_mod)
end
Expand Down
24 changes: 21 additions & 3 deletions installer/templates/phx_single/lib/app_name/application.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
defmodule <%= app_module %>.Application do
use Application

# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false

use Application
<%= if Version.match?(elixir_version, "< 1.5.0") do %>
def start(_type, _args) do
import Supervisor.Spec

Expand All @@ -20,7 +22,23 @@ defmodule <%= app_module %>.Application do
# for other strategies and supported options
opts = [strategy: :one_for_one, name: <%= app_module %>.Supervisor]
Supervisor.start_link(children, opts)
end
end<% else %>
def start(_type, _args) do
# List all child processes to be supervised
children = [<%= if ecto do %>
# Start the Ecto repository
<%= app_module %>.Repo,<% end %>
# Start the endpoint when the application starts
<%= endpoint_module %>,
# Starts a worker by calling: <%= app_module %>.Worker.start_link(arg)
# {<%= app_module %>.Worker, arg},
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: <%= app_module %>.Supervisor]
Supervisor.start_link(children, opts)
end<% end %>

# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ defmodule <%= app_module %>.Application do
for use in channels, controllers, and elsewhere.
"""
use Application
<%= if Version.match?(elixir_version, "< 1.5.0") do %>
def start(_type, _args) do<%= if ecto do %>
import Supervisor.Spec

def start(_type, _args) do
import Supervisor.Spec, warn: false

<%= if ecto do %>
Supervisor.start_link([
supervisor(<%= app_module %>.Repo, []),
], strategy: :one_for_one, name: <%= app_module %>.Supervisor)
<% else %>
Supervisor.start_link([], strategy: :one_for_one, name: <%= app_module %>.Supervisor)
<% end %>
end
], strategy: :one_for_one, name: <%= app_module %>.Supervisor)<% else %>
Supervisor.start_link([], strategy: :one_for_one, name: <%= app_module %>.Supervisor)<% end %>
end<% else %>
def start(_type, _args) do<%= if ecto do %>
Supervisor.start_link([
<%= app_module %>.Repo,
], strategy: :one_for_one, name: <%= app_module %>.Supervisor)<% else %>
Supervisor.start_link([], strategy: :one_for_one, name: <%= app_module %>.Supervisor)<% end %>
end<% end %>
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule <%= web_namespace %>.Application do
@moduledoc false
use Application

<%= if Version.match?(elixir_version, "< 1.5.0") do %>
def start(_type, _args) do
import Supervisor.Spec

Expand All @@ -16,7 +17,21 @@ defmodule <%= web_namespace %>.Application do
# for other strategies and supported options
opts = [strategy: :one_for_one, name: <%= web_namespace %>.Supervisor]
Supervisor.start_link(children, opts)
end
end<% else %>
def start(_type, _args) do
# List all child processes to be supervised
children = [
# Start the endpoint when the application starts
<%= endpoint_module %>,
# Starts a worker by calling: <%= web_namespace %>.Worker.start_link(arg)
# {<%= web_namespace %>.Worker, arg},
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: <%= web_namespace %>.Supervisor]
Supervisor.start_link(children, opts)
end<% end %>

# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
Expand Down
38 changes: 37 additions & 1 deletion installer/test/phx_new_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Code.require_file "mix_helper.exs", __DIR__

defmodule Mix.Tasks.Phx.NewTest do
use ExUnit.Case
use ExUnit.Case, async: false
import MixHelper
import ExUnit.CaptureIO

Expand All @@ -19,6 +19,42 @@ defmodule Mix.Tasks.Phx.NewTest do
assert_received {:mix_shell, :info, ["Phoenix v" <> _]}
end

test "new with elixir >= 1.5 child_spec", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.5.0", fn ->
Mix.Tasks.Phx.New.run([@app_name])

assert_file "phx_blog/lib/phx_blog/application.ex", fn file ->
assert file =~ """
children = [
# Start the Ecto repository
PhxBlog.Repo,
# Start the endpoint when the application starts
PhxBlogWeb.Endpoint,
"""
end
end)
end
end

test "new with elixir < 1.5 child_spec", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.3.0", fn ->
Mix.Tasks.Phx.New.run([@app_name])

assert_file "phx_blog/lib/phx_blog/application.ex", fn file ->
assert file =~ """
children = [
# Start the Ecto repository
supervisor(PhxBlog.Repo, []),
# Start the endpoint when the application starts
supervisor(PhxBlogWeb.Endpoint, []),
"""
end
end)
end
end

test "new with defaults" do
in_tmp "new with defaults", fn ->
Mix.Tasks.Phx.New.run([@app_name])
Expand Down
102 changes: 100 additions & 2 deletions installer/test/phx_new_umbrella_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Code.require_file "mix_helper.exs", __DIR__

defmodule Mix.Tasks.Phx.New.UmbrellaTest do
use ExUnit.Case, async: true
use ExUnit.Case, async: false
import MixHelper

@app "phx_umb"
Expand Down Expand Up @@ -29,6 +29,104 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
Path.join(["#{app}_umbrella/apps/#{app}_web", path])
end

describe "new umbrella with elixir >= 1.5 child_spec" do
test "with defaults", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.5.0", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella"])

assert_file app_path(@app, "lib/#{@app}/application.ex"), fn file ->
assert file =~ """
def start(_type, _args) do
Supervisor.start_link([
PhxUmb.Repo,
], strategy: :one_for_one, name: PhxUmb.Supervisor)
end
"""
end

assert_file web_path(@app, "lib/#{@app}_web/application.ex"), fn file ->
assert file =~ """
children = [
# Start the endpoint when the application starts
PhxUmbWeb.Endpoint,
# Starts a worker by calling: PhxUmbWeb.Worker.start_link(arg)
# {PhxUmbWeb.Worker, arg},
]
"""
end
end)
end
end

test "without ecto", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.5.0", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella", "--no-ecto"])

assert_file app_path(@app, "lib/#{@app}/application.ex"), fn file ->
refute file =~ "children ="
assert file =~ """
def start(_type, _args) do
Supervisor.start_link([], strategy: :one_for_one, name: PhxUmb.Supervisor)
end
"""
end
end)
end
end
end

describe "new umbrella with elixir < 1.5" do
test "with defaults", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.3.0", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella"])

assert_file app_path(@app, "lib/#{@app}/application.ex"), fn file ->
assert file =~ """
def start(_type, _args) do
import Supervisor.Spec
Supervisor.start_link([
supervisor(PhxUmb.Repo, []),
], strategy: :one_for_one, name: PhxUmb.Supervisor)
end
"""
end

assert_file web_path(@app, "lib/#{@app}_web/application.ex"), fn file ->
assert file =~ """
children = [
# Start the endpoint when the application starts
supervisor(PhxUmbWeb.Endpoint, []),
# Start your own worker by calling: PhxUmbWeb.Worker.start_link(arg1, arg2, arg3)
# worker(PhxUmbWeb.Worker, [arg1, arg2, arg3]),
]
"""
end
end)
end
end

test "without ecto", config do
in_tmp to_string(config.test), fn ->
Phx.New.Generator.stub_elixir_version("1.3.0", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella", "--no-ecto"])

assert_file app_path(@app, "lib/#{@app}/application.ex"), fn file ->
refute file =~ "children ="
assert file =~ """
def start(_type, _args) do
Supervisor.start_link([], strategy: :one_for_one, name: PhxUmb.Supervisor)
end
"""
end
end)
end
end
end

test "new with umbrella and defaults" do
in_tmp "new with umbrella and defaults", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella"])
Expand Down Expand Up @@ -73,7 +171,7 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
end

assert_file app_path(@app, "lib/#{@app}/application.ex"), ~r/defmodule PhxUmb.Application do/
assert_file app_path(@app, "lib/#{@app}/application.ex"), ~r/supervisor\(PhxUmb.Repo, \[\]\)/
assert_file app_path(@app, "lib/#{@app}/application.ex"), ~r/PhxUmb.Repo/
assert_file app_path(@app, "lib/#{@app}.ex"), ~r/defmodule PhxUmb do/
assert_file app_path(@app, "mix.exs"), ~r/mod: {PhxUmb.Application, \[\]}/
assert_file app_path(@app, "test/test_helper.exs")
Expand Down

0 comments on commit 2b4ecc4

Please sign in to comment.