{"title":"Upgrading from 1.1.x to 1.2.0","slug":"upgrading-from-11x-to-120","body":"https://gist.github.com/chrismccord/29100e16d3990469c47f851e3142f766\n\n## Project Generator\n\nTo generate new projects as 1.2.0, install the new mix archive:\n\n mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez\n \n## Deps\n\nUpdate your phoenix dep for phoenix and include the extracted `:phoenix_pubsub` depdendency. If using Ecto, bump your `:phoenix_ecto` dependency as well:\n\n```elixir\n# mix.exs\ndef deps do\n [{:phoenix, \"~> 1.2.0\"},\n {:phoenix_pubsub, \"~> 1.0\"},\n # if using Ecto:\n {:phoenix_ecto, \"~> 3.0-rc\"},\n ...]\nend\n```\n\nNext, add `:phoenix_pubsub` to your `:applications` list in mix.exs:\n\n```elixir\n def application do\n [mod: {MyApp, []},\n applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,\n :phoenix_ecto, :postgrex]]\n end\n```\n\nNext, update your deps:\n\n $ mix deps.update phoenix phoenix_pubsub phoenix_ecto phoenix_live_reload phoenix_html --unlock\n\n## Tests\n\nThe `conn/0` helper imported into your tests has been deprecated. use `build_conn/0` instead.\n\n## Ecto 2.0\n\nIf using Ecto, update your test_helper.exs:\n\n```diff\nExUnit.start\n\n- Mix.Task.run \"ecto.create\", ~w(-r Onetwo.Repo --quiet)\n- Mix.Task.run \"ecto.migrate\", ~w(-r Onetwo.Repo --quiet)\n- Ecto.Adapters.SQL.begin_test_transaction(Onetwo.Repo)\n+ Ecto.Adapters.SQL.Sandbox.mode(MyAPp.Repo, :manual)\n```\n\nNext, add the following to `config/config.exs`:\n\n```elixir\nconfig :my_app, ecto_repos: [MyApp.Repo]\n```\n\nNext, add a new `test` alias to your `aliases` in mix.exs:\n\n```diff\n defp aliases do\n [\"ecto.setup\": [\"ecto.create\", \"ecto.migrate\", \"run priv/repo/seeds.exs\"],\n \"ecto.reset\": [\"ecto.drop\", \"ecto.setup\"],\n+ \"test\": [\"ecto.create --quiet\", \"ecto.migrate\", \"test\"]]\n end\n```\n\nNext, update your `setup` blocks in `test/support/model_case.ex` and `test/support/channel_case.ex`:\n\n```diff\n setup tags do\n- unless tags[:async] do\n- Ecto.Adapters.SQL.restart_test_transaction(MyApp.Repo, [])\n- end\n\n+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)\n\n+ unless tags[:async] do\n+ Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})\n+ end\n\n :ok\n end\n```\n\nAnd update your `test/support/conn_case.ex`:\n\n```diff\n setup tags do\n- unless tags[:async] do\n- Ecto.Adapters.SQL.restart_test_transaction(MyApp.Repo, [])\n- end\n\n- {:ok, conn: Phoenix.ConnTest.conn()}\n+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)\n\n+ unless tags[:async] do\n+ Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})\n+ end\n\n+ {:ok, conn: Phoenix.ConnTest.build_conn()}\n end\n```\n\nPassing `:empty` to `cast` has been deprecated. Pass an empty map in your changesets instead:\n\n```diff\n- def changeset(struct, params \\\\ :empty) do\n+ def changeset(struct, params \\\\ %{}) do\n```\n\n## ErrorHelpers\n\nUpdate your `translate_error` function in `web/views/error_helpers.ex`:\n\n```diff\n- @doc \"\"\"\n- Translates an error message using gettext.\n- \"\"\"\n- def translate_error({msg, opts}) do\n- # Because error messages were defined within Ecto, we must\n- # call the Gettext module passing our Gettext backend. We\n- # also use the \"errors\" domain as translations are placed\n- # in the errors.po file. On your own code and templates,\n- # this could be written simply as:\n- #\n- # dngettext \"errors\", \"1 file\", \"%{count} files\", count\n- #\n- Gettext.dngettext(MyApp.Gettext, \"errors\", msg, msg, opts[:count], opts)\n- end\n\n- def translate_error(msg) do\n- Gettext.dgettext(MyApp.Gettext, \"errors\", msg)\n- end\n+def translate_error({msg, opts}) do\n+ # Because error messages were defined within Ecto, we must\n+ # call the Gettext module passing our Gettext backend. We\n+ # also use the \"errors\" domain as translations are placed\n+ # in the errors.po file.\n+ # Ecto will pass the :count keyword if the error message is\n+ # meant to be pluralized.\n+ # On your own code and templates, depending on whether you\n+ # need the message to be pluralized or not, this could be\n+ # written simply as:\n+ #\n+ # dngettext \"errors\", \"1 file\", \"%{count} files\", count\n+ # dgettext \"errors\", \"is invalid\"\n+ #\n+ if count = opts[:count] do\n+ Gettext.dngettext(MyApp.Gettext, \"errors\", msg, msg, count, opts)\n+ else\n+ Gettext.dgettext(MyApp.Gettext, \"errors\", msg, opts)\n+ end\n+ end\n```\n\nNext, update your `test/support/model_case.ex`'s `errors_on` function:\n\n```diff\n- def errors_on(model, data) do\n- model.__struct__.changeset(model, data).errors\n- end\n \n+ def errors_on(struct, data) do\n+ struct.__struct__.changeset(struct, data)\n+ |> Ecto.Changeset.traverse_errors(&MyApp.ErrorHelpers.translate_error/1)\n+ |> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)\n+ end\n```\n## Configuration\n\n### Watcher\n\nUsing 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:\n\n```elixir\nwatchers: [node: [\"node_modules/brunch/bin/brunch\", \"watch\", \"--stdin\",\n cd: Path.expand(\"../\", __DIR__)]]\n```\n\n### Namespace\n\nChange `app_namespace:` in the application configuration to `namespace:`.\n\n```diff\n config :my_app,\n+ namespace: My.App\n- app_namespace: My.App\n```\n\n## JavaScript Client\n\nIf using brunch, run `npm update phoenix phoenix_html`.\n\nIf vendoring the phoenix.js JavaScript client, grab a new copy:\nhttps://raw.githubusercontent.com/phoenixframework/phoenix/v1.2.0/web/static/js/phoenix.js","_id":"57b4bc5bd45e730e0078d3d3","project":"54348ec95b10711400c6c445","createdAt":"2016-08-17T19:34:51.070Z","changelog":[],"user":{"name":"Jason Stiebs","username":"","_id":"5435e00ad7d8700800bbec51"},"__v":0,"metadata":{"title":"","description":"","image":[]}}
https://gist.github.com/chrismccord/29100e16d3990469c47f851e3142f766
## 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:
```elixir
# 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:
```elixir
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:
```diff
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`:
```elixir
config :my_app, ecto_repos: [MyApp.Repo]
```
Next, add a new `test` alias to your `aliases` in mix.exs:
```diff
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`:
```diff
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`:
```diff
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:
```diff
- def changeset(struct, params \\ :empty) do
+ def changeset(struct, params \\ %{}) do
```
## ErrorHelpers
Update your `translate_error` function in `web/views/error_helpers.ex`:
```diff
- @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:
```diff
- 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:
```elixir
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../", __DIR__)]]
```
### Namespace
Change `app_namespace:` in the application configuration to `namespace:`.
```diff
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