diff --git a/assets/js/phoenix/socket.js b/assets/js/phoenix/socket.js index 41e9760547..639e7a8aeb 100644 --- a/assets/js/phoenix/socket.js +++ b/assets/js/phoenix/socket.js @@ -131,6 +131,7 @@ export default class Socket { // transportConnect sets it to false on open. this.closeWasClean = true this.disconnecting = false + this.intentionallyDisconnected = false this.binaryType = opts.binaryType || "arraybuffer" this.connectClock = 1 this.pageHidden = false @@ -160,8 +161,8 @@ export default class Socket { this.pageHidden = true } else { this.pageHidden = false - // reconnect immediately - if(!this.isConnected() && !this.closeWasClean){ + // reconnect immediately if not intentionally disconnected + if(!this.isConnected() && !this.closeWasClean && !this.intentionallyDisconnected){ this.teardown(() => this.connect()) } } @@ -260,6 +261,7 @@ export default class Socket { disconnect(callback, code, reason){ this.connectClock++ this.disconnecting = true + this.intentionallyDisconnected = true this.closeWasClean = true clearTimeout(this.fallbackTimer) this.reconnectTimer.reset() @@ -277,6 +279,7 @@ export default class Socket { * `new Socket("/socket", {params: {user_id: userToken}})`. */ connect(params){ + this.intentionallyDisconnected = false if(params){ console && console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor") this.params = closure(params) diff --git a/installer/lib/phx_new/project.ex b/installer/lib/phx_new/project.ex index 36885b37d1..3480a93dc1 100644 --- a/installer/lib/phx_new/project.ex +++ b/installer/lib/phx_new/project.ex @@ -22,6 +22,7 @@ defmodule Phx.New.Project do def new(project_path, opts) do project_path = Path.expand(project_path) app = opts[:app] || Path.basename(project_path) + app_mod = Module.concat([opts[:module] || Macro.camelize(app)]) %Project{ @@ -79,7 +80,10 @@ defmodule Phx.New.Project do defp expand_path_with_bindings(path, %Project{} = project) do Regex.replace(Regex.recompile!(~r/:[a-zA-Z0-9_]+/), path, fn ":" <> key, _ -> - project |> Map.fetch!(:"#{key}") |> to_string() + case Map.fetch(project, :"#{key}") do + {:ok, value} -> to_string(value) + :error -> ":#{key}" + end end) end end diff --git a/lib/phoenix/router.ex b/lib/phoenix/router.ex index 763d45da64..d138d24850 100644 --- a/lib/phoenix/router.ex +++ b/lib/phoenix/router.ex @@ -328,49 +328,49 @@ defmodule Phoenix.Router do if resource.singleton do Enum.each(resource.actions, fn :show -> - get path, ctrl, :show, opts + get(path, ctrl, :show, opts) :new -> - get path <> "/new", ctrl, :new, opts + get(path <> "/new", ctrl, :new, opts) :edit -> - get path <> "/edit", ctrl, :edit, opts + get(path <> "/edit", ctrl, :edit, opts) :create -> - post path, ctrl, :create, opts + post(path, ctrl, :create, opts) :delete -> - delete path, ctrl, :delete, opts + delete(path, ctrl, :delete, opts) :update -> - patch path, ctrl, :update, opts - put path, ctrl, :update, Keyword.put(opts, :as, nil) + patch(path, ctrl, :update, opts) + put(path, ctrl, :update, Keyword.put(opts, :as, nil)) end) else param = resource.param Enum.each(resource.actions, fn :index -> - get path, ctrl, :index, opts + get(path, ctrl, :index, opts) :show -> - get path <> "/:" <> param, ctrl, :show, opts + get(path <> "/:" <> param, ctrl, :show, opts) :new -> - get path <> "/new", ctrl, :new, opts + get(path <> "/new", ctrl, :new, opts) :edit -> - get path <> "/:" <> param <> "/edit", ctrl, :edit, opts + get(path <> "/:" <> param <> "/edit", ctrl, :edit, opts) :create -> - post path, ctrl, :create, opts + post(path, ctrl, :create, opts) :delete -> - delete path <> "/:" <> param, ctrl, :delete, opts + delete(path <> "/:" <> param, ctrl, :delete, opts) :update -> - patch path <> "/:" <> param, ctrl, :update, opts - put path <> "/:" <> param, ctrl, :update, Keyword.put(opts, :as, nil) + patch(path <> "/:" <> param, ctrl, :update, opts) + put(path <> "/:" <> param, ctrl, :update, Keyword.put(opts, :as, nil)) end) end end @@ -1302,6 +1302,7 @@ defmodule Phoenix.Router do helper: route.helper, verb: route.verb, path: route.path, + hosts: route.hosts, label: label } ] diff --git a/lib/phoenix/router/console_formatter.ex b/lib/phoenix/router/console_formatter.ex index f8085094c8..9ef92114be 100644 --- a/lib/phoenix/router/console_formatter.ex +++ b/lib/phoenix/router/console_formatter.ex @@ -78,29 +78,39 @@ defmodule Phoenix.Router.ConsoleFormatter do sockets = (endpoint && endpoint.__sockets__()) || [] widths = - Enum.reduce(routes, {0, 0, 0}, fn route, acc -> + Enum.reduce(routes, {0, 0, 0, 0}, fn route, acc -> %{verb: verb, path: path, helper: helper} = route verb = verb_name(verb) - {verb_len, path_len, route_name_len} = acc + {hosts_len, verb_len, path_len, route_name_len} = acc route_name = route_name(router, helper) + hosts_width = hosts_column_width(Map.get(route, :hosts, [])) - {max(verb_len, String.length(verb)), max(path_len, String.length(path)), - max(route_name_len, String.length(route_name))} + {max(hosts_len, hosts_width), max(verb_len, String.length(verb)), + max(path_len, String.length(path)), max(route_name_len, String.length(route_name))} end) Enum.reduce(sockets, widths, fn {path, _mod, opts}, acc -> - {verb_len, path_len, route_name_len} = acc + {hosts_len, verb_len, path_len, route_name_len} = acc verb_length = socket_verbs(opts) |> Enum.map(&String.length/1) |> Enum.max(&>=/2, fn -> 0 end) - {max(verb_len, verb_length), max(path_len, String.length(path <> "/websocket")), + {hosts_len, max(verb_len, verb_length), max(path_len, String.length(path <> "/websocket")), route_name_len} end) end + defp hosts_column_width([]), do: 0 + + defp hosts_column_width(hosts) when is_list(hosts) do + host_str = Enum.join(hosts, ", ") + String.length("[#{host_str}]") + 2 + end + + defp hosts_column_width(_), do: 0 + defp format_route(route, router, column_widths) do %{ verb: verb, @@ -110,9 +120,11 @@ defmodule Phoenix.Router.ConsoleFormatter do verb = verb_name(verb) route_name = route_name(router, Map.get(route, :helper)) - {verb_len, path_len, route_name_len} = column_widths + hosts = format_hosts(Map.get(route, :hosts, [])) + {hosts_len, verb_len, path_len, route_name_len} = column_widths - String.pad_leading(route_name, route_name_len) <> + String.pad_trailing(hosts, hosts_len) <> + String.pad_leading(route_name, route_name_len) <> " " <> String.pad_trailing(verb, verb_len) <> " " <> @@ -121,6 +133,15 @@ defmodule Phoenix.Router.ConsoleFormatter do label <> "\n" end + defp format_hosts([]), do: "" + + defp format_hosts(hosts) when is_list(hosts) do + host_str = Enum.join(hosts, ", ") + "[#{host_str}]" + end + + defp format_hosts(_), do: "" + defp route_name(_router, nil), do: "" defp route_name(router, name) do diff --git a/lib/phoenix/verified_routes.ex b/lib/phoenix/verified_routes.ex index 0585bde717..5e53302561 100644 --- a/lib/phoenix/verified_routes.ex +++ b/lib/phoenix/verified_routes.ex @@ -927,6 +927,18 @@ defmodule Phoenix.VerifiedRoutes do defp build_route(route_ast, sigil_p, env, endpoint_ctx, router) do config = Module.get_attribute(env.module, :phoenix_verified_config, []) + if config == [] do + raise ArgumentError, """ + attempted to use Phoenix.VerifiedRoutes without calling `use Phoenix.VerifiedRoutes` first. + + You must use `use Phoenix.VerifiedRoutes` with the appropriate options instead of importing it: + + use Phoenix.VerifiedRoutes, endpoint: MyAppWeb.Endpoint, router: MyAppWeb.Router + + See the documentation for more details on configuration options. + """ + end + router = case Macro.expand(router, env) do mod when is_atom(mod) ->