Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?

#Phoenix 1.1.x to 1.2.0 Upgrade Instructions

Project Generator

To generate new projects as 1.2.0, install the new mix archive:

mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez

Deps

Update your phoenix dep for phoenix and include the extracted :phoenix_pubsub depdendency. If using Ecto, bump your :phoenix_ecto dependency as well:

# mix.exs
def deps do
  [{:phoenix, "~> 1.2.0"},
   {:phoenix_pubsub, "~> 1.0"},
   # if using Ecto:
   {:phoenix_ecto, "~> 3.0-rc"},
   ...]
end

Next, add :phoenix_pubsub to your :applications list in mix.exs:

  def application do
    [mod: {MyApp, []},
     applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
                    :phoenix_ecto, :postgrex]]
  end

Next, update your deps:

$ mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload phoenix_html --unlock

Tests

The conn/0 helper imported into your tests has been deprecated. use build_conn/0 instead.

Ecto 2.0

If using Ecto, update your test_helper.exs:

ExUnit.start

- Mix.Task.run "ecto.create", ~w(-r Onetwo.Repo --quiet)
- Mix.Task.run "ecto.migrate", ~w(-r Onetwo.Repo --quiet)
- Ecto.Adapters.SQL.begin_test_transaction(Onetwo.Repo)
+ Ecto.Adapters.SQL.Sandbox.mode(MyAPp.Repo, :manual)

Next, add the following to config/config.exs:

config :my_app, ecto_repos: [MyApp.Repo]

Next, add a new test alias to your aliases in mix.exs:

  defp aliases do
    ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
     "ecto.reset": ["ecto.drop", "ecto.setup"],
+    "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
  end

Next, update your setup blocks in test/support/model_case.ex and test/support/channel_case.ex:

  setup tags do
-   unless tags[:async] do
-     Ecto.Adapters.SQL.restart_test_transaction(MyApp.Repo, [])
-   end

+   :ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)

+   unless tags[:async] do
+     Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})
+   end

    :ok
  end

And update your test/support/conn_case.ex:

  setup tags do
-   unless tags[:async] do
-     Ecto.Adapters.SQL.restart_test_transaction(MyApp.Repo, [])
-   end

-   {:ok, conn: Phoenix.ConnTest.conn()}
+   :ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)

+   unless tags[:async] do
+     Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})
+   end

+   {:ok, conn: Phoenix.ConnTest.build_conn()}
  end

Passing :empty to cast has been deprecated. Pass an empty map in your changesets instead:

-  def changeset(struct, params \\ :empty) do
+  def changeset(struct, params \\ %{}) do

ErrorHelpers

Update your translate_error function in web/views/error_helpers.ex:

- @doc """
- Translates an error message using gettext.
- """
- def translate_error({msg, opts}) do
-   # Because error messages were defined within Ecto, we must
-   # call the Gettext module passing our Gettext backend. We
-   # also use the "errors" domain as translations are placed
-   # in the errors.po file. On your own code and templates,
-   # this could be written simply as:
-   #
-   #     dngettext "errors", "1 file", "%{count} files", count
-   #
-   Gettext.dngettext(MyApp.Gettext, "errors", msg, msg, opts[:count], opts)
- end

- def translate_error(msg) do
-   Gettext.dgettext(MyApp.Gettext, "errors", msg)
- end
+def translate_error({msg, opts}) do
+   # Because error messages were defined within Ecto, we must
+   # call the Gettext module passing our Gettext backend. We
+   # also use the "errors" domain as translations are placed
+   # in the errors.po file.
+   # Ecto will pass the :count keyword if the error message is
+   # meant to be pluralized.
+   # On your own code and templates, depending on whether you
+   # need the message to be pluralized or not, this could be
+   # written simply as:
+   #
+   #     dngettext "errors", "1 file", "%{count} files", count
+   #     dgettext "errors", "is invalid"
+   #
+   if count = opts[:count] do
+     Gettext.dngettext(MyApp.Gettext, "errors", msg, msg, count, opts)
+   else
+     Gettext.dgettext(MyApp.Gettext, "errors", msg, opts)
+   end
+ end

Next, update your test/support/model_case.ex's errors_on function:

-  def errors_on(model, data) do
-    model.__struct__.changeset(model, data).errors
-  end
  
+  def errors_on(struct, data) do
+    struct.__struct__.changeset(struct, data)
+    |> Ecto.Changeset.traverse_errors(&MyApp.ErrorHelpers.translate_error/1)
+    |> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)
+  end

Configuration

Watcher

Using the :root endpoint configuration for watchers is deprecated and can be removed from config/config.exs. Instead, pass the :cd option at the end of your watcher argument list in config/dev.exs. For example:

watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
           cd: Path.expand("../", __DIR__)]]

Namespace

Change app_namespace: in the application configuration to namespace:.

 config :my_app,
+  namespace: My.App
-  app_namespace: My.App

JavaScript Client

If using brunch, run npm update phoenix phoenix_html.

If vendoring the phoenix.js JavaScript client, grab a new copy: https://raw.githubusercontent.com/phoenixframework/phoenix/v1.2.0/web/static/js/phoenix.js

@younesmln

This comment has been minimized.

Show comment
Hide comment

thinks

@boriscy

This comment has been minimized.

Show comment
Hide comment
@boriscy

boriscy Apr 29, 2016

Great thanks

boriscy commented Apr 29, 2016

Great thanks

@kipcole9

This comment has been minimized.

Show comment
Hide comment
@kipcole9

kipcole9 Apr 29, 2016

I had to mix deps.unlock phoenix_live_reload to avoid:

Running dependency resolution
Conflict on phoenix 1.2.0-rc.0
  mix.exs: ~> 1.2.0-rc
  phoenix_live_reload 1.0.3: ~> 0.16 or ~> 1.0

Otherwise great to see this out, its great work.

I had to mix deps.unlock phoenix_live_reload to avoid:

Running dependency resolution
Conflict on phoenix 1.2.0-rc.0
  mix.exs: ~> 1.2.0-rc
  phoenix_live_reload 1.0.3: ~> 0.16 or ~> 1.0

Otherwise great to see this out, its great work.

@jerel

This comment has been minimized.

Show comment
Hide comment
@jerel

jerel Apr 29, 2016

I was using ja_serializer which depends on ecto 1.0 so I had to add {:ecto, "~> 2.0.0-rc.3", override: true} to solve:

Conflict on ecto from 2.0.0-beta.0 to 2.0.0-rc.3
  ja_serializer 0.8.1: ~> 1.0
  phoenix_ecto from 3.0.0-beta.0 to 3.0.0-beta.2: ~> 2.0-beta

Conflict on ecto from 2.0.0-beta.0 to 2.0.0-rc.3
  ja_serializer 0.8.1: ~> 1.0
  phoenix_ecto 3.0.0-rc.0: ~> 2.0.0-rc

It appears to be working well.

jerel commented Apr 29, 2016

I was using ja_serializer which depends on ecto 1.0 so I had to add {:ecto, "~> 2.0.0-rc.3", override: true} to solve:

Conflict on ecto from 2.0.0-beta.0 to 2.0.0-rc.3
  ja_serializer 0.8.1: ~> 1.0
  phoenix_ecto from 3.0.0-beta.0 to 3.0.0-beta.2: ~> 2.0-beta

Conflict on ecto from 2.0.0-beta.0 to 2.0.0-rc.3
  ja_serializer 0.8.1: ~> 1.0
  phoenix_ecto 3.0.0-rc.0: ~> 2.0.0-rc

It appears to be working well.

@talklittle

This comment has been minimized.

Show comment
Hide comment
@talklittle

talklittle Apr 30, 2016

My translate_error function was found in web/views/error_helpers.ex instead of web/gettext.ex

My translate_error function was found in web/views/error_helpers.ex instead of web/gettext.ex

@thbar

This comment has been minimized.

Show comment
Hide comment
@thbar

thbar May 4, 2016

Amazing, thanks for sharing!

thbar commented May 4, 2016

Amazing, thanks for sharing!

@thbar

This comment has been minimized.

Show comment
Hide comment
@thbar

thbar May 6, 2016

I think (well at least I had to do this) that the guidelines here are lacking config :my_app, ecto_repos: [MyApp.Repo] described here.

thbar commented May 6, 2016

I think (well at least I had to do this) that the guidelines here are lacking config :my_app, ecto_repos: [MyApp.Repo] described here.

@thbar

This comment has been minimized.

Show comment
Hide comment
@thbar

thbar May 7, 2016

I needed to mkdir priv/repo/migrations for this app which hadn't any migration yet, to get the upgrade working.

thbar commented May 7, 2016

I needed to mkdir priv/repo/migrations for this app which hadn't any migration yet, to get the upgrade working.

@technicalcapt

This comment has been minimized.

Show comment
Hide comment
@technicalcapt

technicalcapt May 11, 2016

Thanks @jerel for sharing.

Thanks @jerel for sharing.

@karmajunkie

This comment has been minimized.

Show comment
Hide comment
@karmajunkie

karmajunkie May 12, 2016

I had to drop my dependency on phoenix_pubsub_redis to get the upgrade to start up properly. I didn't see any recent work in the repo so not sure what the plans are for that application

I had to drop my dependency on phoenix_pubsub_redis to get the upgrade to start up properly. I didn't see any recent work in the repo so not sure what the plans are for that application

@jwmatthews

This comment has been minimized.

Show comment
Hide comment
@jwmatthews

jwmatthews May 15, 2016

@jerel thanks for the workaround with {:ecto, "~> 2.0.0-rc.3", override: true}

@jerel thanks for the workaround with {:ecto, "~> 2.0.0-rc.3", override: true}

@zhangsoledad

This comment has been minimized.

Show comment
Hide comment
@zhangsoledad

zhangsoledad May 16, 2016

actually you need

mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload --unlock

actually you need

mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload --unlock

@endersstocker

This comment has been minimized.

Show comment
Hide comment
@endersstocker

endersstocker May 16, 2016

Shouldn’t it be:

Update your translate_error function in web/views/error_helpers.ex

Shouldn’t it be:

Update your translate_error function in web/views/error_helpers.ex

@rubas

This comment has been minimized.

Show comment
Hide comment

rubas commented May 20, 2016

Thanks @endersstocker.

@endersstocker

This comment has been minimized.

Show comment
Hide comment
@endersstocker

endersstocker May 24, 2016

Missing step:

Change app_namespace: in the application configuration to namespace:.

 config :my_app,
+  namespace: My.App
-  app_namespace: My.App

mix phoenix.gen.* and mix phoenix.routes will not work correctly without this step if your app uses a custom namespace.

Missing step:

Change app_namespace: in the application configuration to namespace:.

 config :my_app,
+  namespace: My.App
-  app_namespace: My.App

mix phoenix.gen.* and mix phoenix.routes will not work correctly without this step if your app uses a custom namespace.

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany May 27, 2016

Agreed with @endersstocker and @talklittle regarding the location of translate_error.

nathany commented May 27, 2016

Agreed with @endersstocker and @talklittle regarding the location of translate_error.

@JulianLeviston

This comment has been minimized.

Show comment
Hide comment
@JulianLeviston

JulianLeviston Jun 23, 2016

Under Ecto 2, small capitalisation typo for + Ecto.Adapters.SQL.Sandbox.mode(MyAPp.Repo, :manual) should have MyApp rather than MyAPp.

Under Ecto 2, small capitalisation typo for + Ecto.Adapters.SQL.Sandbox.mode(MyAPp.Repo, :manual) should have MyApp rather than MyAPp.

@cas27

This comment has been minimized.

Show comment
Hide comment
@cas27

cas27 Jun 24, 2016

Might throw in a note about rm -rf _build directory if you're getting compile errors like I did.

cas27 commented Jun 24, 2016

Might throw in a note about rm -rf _build directory if you're getting compile errors like I did.

@nicbet

This comment has been minimized.

Show comment
Hide comment
@nicbet

nicbet Jun 26, 2016

As others have noted:

mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload --unlock
rm -rf _build

did the trick for me after doing all the file modifications outlined in the upgrade guide.

nicbet commented Jun 26, 2016

As others have noted:

mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload --unlock
rm -rf _build

did the trick for me after doing all the file modifications outlined in the upgrade guide.

@tracehelms

This comment has been minimized.

Show comment
Hide comment
@tracehelms

tracehelms Jul 12, 2016

After upgrading I was getting these warnings in every Model:

warning: using Ecto.Model is deprecated, please use Ecto.Schema instead
    web/models/user.ex:2: MyApp.User (module)

To fix them, inside web/web.ex I changed this:

  def model do
    quote do
      use Ecto.Model
    end
  end

to this:

  def model do
    quote do
      use Ecto.Schema

      import Ecto
      import Ecto.Changeset
      import Ecto.Query
    end
  end

Should this be added to the upgrade instructions or did I miss something from a previous version?

After upgrading I was getting these warnings in every Model:

warning: using Ecto.Model is deprecated, please use Ecto.Schema instead
    web/models/user.ex:2: MyApp.User (module)

To fix them, inside web/web.ex I changed this:

  def model do
    quote do
      use Ecto.Model
    end
  end

to this:

  def model do
    quote do
      use Ecto.Schema

      import Ecto
      import Ecto.Changeset
      import Ecto.Query
    end
  end

Should this be added to the upgrade instructions or did I miss something from a previous version?

@olivermt

This comment has been minimized.

Show comment
Hide comment
@olivermt

olivermt Jul 13, 2016

@tracehelms that is from a previous upgrade

@tracehelms that is from a previous upgrade

@jgrau

This comment has been minimized.

Show comment
Hide comment
@jgrau

jgrau Jul 15, 2016

I had some integration tests that used Plug.Test directly instead of MyApp.ConnCase and the conn helper you get from Plug.Test did not work correctly with Ecto 2.0 and I got

** (Plug.Conn.WrapperError) ** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.283.0>.

Changing the integration tests to use MyApp.ConnCase instead of Plug.Test and using build_conn() instead of conn() fixed the issue.

jgrau commented Jul 15, 2016

I had some integration tests that used Plug.Test directly instead of MyApp.ConnCase and the conn helper you get from Plug.Test did not work correctly with Ecto 2.0 and I got

** (Plug.Conn.WrapperError) ** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.283.0>.

Changing the integration tests to use MyApp.ConnCase instead of Plug.Test and using build_conn() instead of conn() fixed the issue.

@HeroicEric

This comment has been minimized.

Show comment
Hide comment
@HeroicEric

HeroicEric Aug 8, 2016

You'll also want to remove the following from your test/support/model_case.ex's errors_on function:


  You can also create the changeset manually and retrieve the errors
  field directly:

      iex> changeset = User.changeset(%User{}, password: "password")
      iex> {:password, "is unsafe"} in changeset.errors
      true

You'll also want to remove the following from your test/support/model_case.ex's errors_on function:


  You can also create the changeset manually and retrieve the errors
  field directly:

      iex> changeset = User.changeset(%User{}, password: "password")
      iex> {:password, "is unsafe"} in changeset.errors
      true
@campezzi

This comment has been minimized.

Show comment
Hide comment
@campezzi

campezzi Aug 9, 2016

Might be worth updating the phoenix_ecto dependency so it says ~> 3.0.0 since the RC was now officially released :)

campezzi commented Aug 9, 2016

Might be worth updating the phoenix_ecto dependency so it says ~> 3.0.0 since the RC was now officially released :)

@edave

This comment has been minimized.

Show comment
Hide comment
@edave

edave Oct 9, 2016

When I try to run mix phoenix.server after upgrading, I receive this error message:

    application: logger
    exited: stopped
    type: temporary
** (Mix) Could not start application my_app: MyApp.start(:normal, []) returned an error: shutdown: failed to start child: MyApp.Endpoint
    ** (EXIT) an exception was raised:
        ** (Protocol.UndefinedError) protocol Enumerable not implemented for "/Users/dave/repositories/my_app"
            (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
            (elixir) lib/enum.ex:116: Enumerable.reduce/3
            (elixir) lib/enum.ex:1636: Enum.reduce/3
            (elixir) lib/enum.ex:2086: Enum.split_while/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:72: Phoenix.Endpoint.Adapter.watcher_args/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:64: anonymous fn/1 in Phoenix.Endpoint.Adapter.watcher_children/3
            (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
            (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:21: Phoenix.Endpoint.Adapter.start_link/2
            (stdlib) supervisor.erl:358: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:341: :supervisor.start_children/3
            (stdlib) supervisor.erl:307: :supervisor.init_children/2
            (stdlib) gen_server.erl:328: :gen_server.init_it/6
            (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Any ideas of why this may be happening? I've updated all dependencies and rm -rf _build

edave commented Oct 9, 2016

When I try to run mix phoenix.server after upgrading, I receive this error message:

    application: logger
    exited: stopped
    type: temporary
** (Mix) Could not start application my_app: MyApp.start(:normal, []) returned an error: shutdown: failed to start child: MyApp.Endpoint
    ** (EXIT) an exception was raised:
        ** (Protocol.UndefinedError) protocol Enumerable not implemented for "/Users/dave/repositories/my_app"
            (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
            (elixir) lib/enum.ex:116: Enumerable.reduce/3
            (elixir) lib/enum.ex:1636: Enum.reduce/3
            (elixir) lib/enum.ex:2086: Enum.split_while/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:72: Phoenix.Endpoint.Adapter.watcher_args/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:64: anonymous fn/1 in Phoenix.Endpoint.Adapter.watcher_children/3
            (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
            (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
            (phoenix) lib/phoenix/endpoint/adapter.ex:21: Phoenix.Endpoint.Adapter.start_link/2
            (stdlib) supervisor.erl:358: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:341: :supervisor.start_children/3
            (stdlib) supervisor.erl:307: :supervisor.init_children/2
            (stdlib) gen_server.erl:328: :gen_server.init_it/6
            (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Any ideas of why this may be happening? I've updated all dependencies and rm -rf _build

@tmjoen

This comment has been minimized.

Show comment
Hide comment
@tmjoen

tmjoen Oct 10, 2016

@edave: looks like an error in the watcher_args, so maybe you've got a typo when you updated the watchers key in your endpoint?

watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
           cd: Path.expand("../", __DIR__)]]

tmjoen commented Oct 10, 2016

@edave: looks like an error in the watcher_args, so maybe you've got a typo when you updated the watchers key in your endpoint?

watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
           cd: Path.expand("../", __DIR__)]]
@kelvinst

This comment has been minimized.

Show comment
Hide comment
@kelvinst

kelvinst Nov 12, 2016

Update your phoenix dep for phoenix and include the extracted :phoenix_pubsub depdendency.

Just a little typo @chrismccord. :)

Update your phoenix dep for phoenix and include the extracted :phoenix_pubsub depdendency.

Just a little typo @chrismccord. :)

@silbermm

This comment has been minimized.

Show comment
Hide comment
@silbermm

silbermm Feb 4, 2017

I'm trying to update a working app from 1.1.x to 1.2.1 and after following these instructions I get

== Compilation error on file web/views/angular_view.ex==
** (CompileError) web/views/angular_view.ex:2: module CrossroadsInterface.Router.Helpers is not loaded and could not be found
    expanding macro: CrossroadsInterface.Web.__using__/1
    web/views/angular_view.ex:2: CrossroadsInterface.AngularView (module)
    (elixir) expanding macro: Kernel.use/2
    web/views/angular_view.ex:2: CrossroadsInterface.AngularView (module)
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

It's not always the same view that fails to compile, it will fail on the first view it trys to compile. My views are all bare bones, for instance, the AngularView in it's entirety is:

defmodule CrossroadsInterface.AngularView do
  use CrossroadsInterface.Web, :view
end

angular_view.ex
Any ideas what might be happening?

Elixir version: 1.4
Phoenix: 1.2.1
No Ecto

Thanks!!

silbermm commented Feb 4, 2017

I'm trying to update a working app from 1.1.x to 1.2.1 and after following these instructions I get

== Compilation error on file web/views/angular_view.ex==
** (CompileError) web/views/angular_view.ex:2: module CrossroadsInterface.Router.Helpers is not loaded and could not be found
    expanding macro: CrossroadsInterface.Web.__using__/1
    web/views/angular_view.ex:2: CrossroadsInterface.AngularView (module)
    (elixir) expanding macro: Kernel.use/2
    web/views/angular_view.ex:2: CrossroadsInterface.AngularView (module)
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

It's not always the same view that fails to compile, it will fail on the first view it trys to compile. My views are all bare bones, for instance, the AngularView in it's entirety is:

defmodule CrossroadsInterface.AngularView do
  use CrossroadsInterface.Web, :view
end

angular_view.ex
Any ideas what might be happening?

Elixir version: 1.4
Phoenix: 1.2.1
No Ecto

Thanks!!

@msp

This comment has been minimized.

Show comment
Hide comment

msp commented Mar 31, 2017

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment