{"_id":"55b648276127b12500364395","tags":[],"project":"54348ec95b10711400c6c445","user":{"_id":"5435b410495d5d0800f3a603","username":"","name":"Lance Halvorsen"},"__v":0,"initVersion":{"_id":"55b6448f6127b12500364357","version":"0.15.0"},"createdAt":"2015-07-27T15:03:03.514Z","changelog":[],"body":"## Sockets and Channels\n\nA new socket behaviour has been introduced to handle socket authentication in a single place, wire up default channel assigns, and disconnect a user's multiplex connection as needed.\n\nFirst things first, create a `UserSocket` module in `web/channels/user_socket.ex` and move all your channel routes from `web/route.ex` to the user socket: (replace MyApp with your application module)\n\n0.14.x - web/router.ex:\n```elixir\ndefmodule MyApp.Router do\n   ...\n  socket \"/ws\", MyApp do\n    channel \"rooms:*\", RoomChannel\n  end\nend\n```\n\n0.15.0 - web/channels/user_socket.ex:\n```elixir\ndefmodule MyApp.UserSocket do\n  use Phoenix.Socket\n\n  ## Channels\n  channel \"rooms:*\", MyApp.RoomChannel\n\n  ## Transports\n  transport :websocket, Phoenix.Transports.WebSocket\n  transport :longpoll, Phoenix.Transports.LongPoll\n\n  # Socket params are passed from the client and can\n  # be used to verify and authenticate a user. After\n  # verification, you can put default assigns into\n  # the socket that will be set for all channels, ie\n  #\n  #     {:ok, assign(socket, :user_id, verified_user_id)}\n  #\n  #  To deny connection, return `:error`.\n  def connect(_params, socket) do\n    {:ok, socket}\n  end\n\n  # Socket id's are topics that allow you to identify all sockets for a given user:\n  #\n  #     def id(socket), do: \"users_socket:#{socket.assigns.user_id}\"\n  #\n  # Would allow you to broadcast a \"disconnect\" event and terminate\n  # all active sockets and channels for a given user:\n  #\n  #     MyApp.Endpoint.broadcast(\"users_socket:\" <> user.id, \"disconnect\", %{})\n  #\n  # Returning `nil` makes this socket anonymous.\n  def id(_socket), do: nil\nend\n```\n\nLeaving the default implementations of `connect/2` and `id/1` will give you the same behavour you had with 0.14.x.\n\nNext, remove the `socket` mount from your Router and add it to your `lib/my_app/endpoint.ex` and add a mount for phoenix live reload if using `:phoenix_live_reload`:\n\n```elixir\ndefmodule MyApp.Endpoint do\n  use Phoenix.Endpoint, otp_app: :my_app\n\n  socket \"/ws\", MyApp.UserSocket\n\n  plug Plug.Static, ...\n\n  # Code reloading can be explicitly enabled under the\n  # :code_reloader configuration of your endpoint.\n  if code_reloading? do\n    socket \"/phoenix/live_reload/socket\", Phoenix.LiveReloader.Socket\n    plug Phoenix.LiveReloader\n    plug Phoenix.CodeReloader\n  end\n  \n  ...\nend\n```\n\n## Endpoint changes\n\nAlso in your endpoint, replace `plug :router, MyApp.Router` with `plug MyApp.Router`, and remove the `:encryption_salt` option from your `plug Plug.Session, ...` options.\n\n### Channel handle_out callbacks\n\nIf using `handle_out/3` callbacks in your channels, you now must explicit list which events you want your channels to intercept and pass through handle_out. This change brings large performance improvements by caching encodings across all subscribers if the event is not intercepted by the channel:\n\n0.14.x:\n```elixir\ndefmodule MyApp.RoomChannel do\n  use MyApp.Web, :channel\n  ...\n  \n  def handle_out(\"new_msg\", payload, socket) do\n    push socket, \"new_msg\", %{role: socket.assigns.role, body: payload[\"body\"]}\n    {:noreply, socket}\n  end\nend\n```\n\n0.15.0:\n```elixir\ndefmodule MyApp.RoomChannel do\n  use MyApp.Web, :channel\n  \n  intercept [\"new_msg\"]\n  ...\n  \n  def handle_out(\"new_msg\", payload, socket) do\n    push socket, \"new_msg\", %{role: socket.assigns.role, body: payload[\"body\"]}\n    {:noreply, socket}\n  end\nend\n```\n\n\n\n## Bump your deps\n\nNext update your `:phoenix`, `:phoenix_html`, `:phoenix_ecto`, and `:phoenix_live_reload` deps in `mix.exs`:\n\n```elixir\ndef deps do\n  [...,\n   {:phoenix, \"~> 0.15\"},\n   {:phoenix_ecto, \"~> 0.8\"},\n   {:phoenix_html, \"~> 1.4\"},\n   {:phoenix_live_reload, \"~> 0.5\", only: :dev},\n  ...]\nend\n```\n\nNext, run `$ mix deps.update --all`\n\n## Grab the latest phoenix.js\n\nUpgrade to the latest phoenix.js client by replacing web/static/vendor/phoenix.js with the latest version: https://raw.githubusercontent.com/phoenixframework/phoenix/f6ffac8e040f764bd365325fd1fcf54db06f7749/priv/static/phoenix.js\n\n## Ecto changes (can skip if not using Ecto)\n\nWe are updating two versions fo Ecto from version 0.12 to 0.14/0.15-dev most of the changes you need to make will be reflected in this section taken from the Ecto Changelog. If you have further issues or compiler errors please check the [Ecto Changelog](https://github.com/elixir-lang/ecto/blob/master/CHANGELOG.md#v0130) for further details. \n\nBelow is taken from the change for v0.13 backwards incompatible changes. \n\n  * `Ecto.Repo.update!/2` no longer invokes callbacks if there were no changes, avoiding writing to the database at all (use `:force` to force callback execution)\n  * `Ecto.Repo.transaction/2` is now flattened. This means that multiple transaction calls will no longer use savepoints, instead it will be considered as a single transaction, where a failure in any transaction block will trigger the outmost transaction to rollback, even if failures are rescued. This should only affect users that were explicitly relying on the savepoints.\n  * `:date`, `:time` and `:datetime` were removed in favor of `Ecto.Date`, `Ecto.Time` and `Ecto.DateTime`\n  * `Ecto.Changeset.errors` now return `{\"must be less than %{count}\", count: 3}` instead of `{\"must be less than %{count}\", 3}`\n\n\n## phoenix_pubsub_redis (skip if not using redis adapter)\n\nUpdate your :phoenix_pubsub_redis dep to the latest release:\n\n```elixir\ndef deps do\n  ...\n  {:phoenix_pubsub_redis, \"~> 0.2.0\"}\n  ...\nend\n```","slug":"upgrading-from-v0140-to-v0150","title":"Upgrading from v0.14.0 to v0.15.0"}

Upgrading from v0.14.0 to v0.15.0


## Sockets and Channels A new socket behaviour has been introduced to handle socket authentication in a single place, wire up default channel assigns, and disconnect a user's multiplex connection as needed. First things first, create a `UserSocket` module in `web/channels/user_socket.ex` and move all your channel routes from `web/route.ex` to the user socket: (replace MyApp with your application module) 0.14.x - web/router.ex: ```elixir defmodule MyApp.Router do ... socket "/ws", MyApp do channel "rooms:*", RoomChannel end end ``` 0.15.0 - web/channels/user_socket.ex: ```elixir defmodule MyApp.UserSocket do use Phoenix.Socket ## Channels channel "rooms:*", MyApp.RoomChannel ## Transports transport :websocket, Phoenix.Transports.WebSocket transport :longpoll, Phoenix.Transports.LongPoll # Socket params are passed from the client and can # be used to verify and authenticate a user. After # verification, you can put default assigns into # the socket that will be set for all channels, ie # # {:ok, assign(socket, :user_id, verified_user_id)} # # To deny connection, return `:error`. def connect(_params, socket) do {:ok, socket} end # Socket id's are topics that allow you to identify all sockets for a given user: # # def id(socket), do: "users_socket:#{socket.assigns.user_id}" # # Would allow you to broadcast a "disconnect" event and terminate # all active sockets and channels for a given user: # # MyApp.Endpoint.broadcast("users_socket:" <> user.id, "disconnect", %{}) # # Returning `nil` makes this socket anonymous. def id(_socket), do: nil end ``` Leaving the default implementations of `connect/2` and `id/1` will give you the same behavour you had with 0.14.x. Next, remove the `socket` mount from your Router and add it to your `lib/my_app/endpoint.ex` and add a mount for phoenix live reload if using `:phoenix_live_reload`: ```elixir defmodule MyApp.Endpoint do use Phoenix.Endpoint, otp_app: :my_app socket "/ws", MyApp.UserSocket plug Plug.Static, ... # Code reloading can be explicitly enabled under the # :code_reloader configuration of your endpoint. if code_reloading? do socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket plug Phoenix.LiveReloader plug Phoenix.CodeReloader end ... end ``` ## Endpoint changes Also in your endpoint, replace `plug :router, MyApp.Router` with `plug MyApp.Router`, and remove the `:encryption_salt` option from your `plug Plug.Session, ...` options. ### Channel handle_out callbacks If using `handle_out/3` callbacks in your channels, you now must explicit list which events you want your channels to intercept and pass through handle_out. This change brings large performance improvements by caching encodings across all subscribers if the event is not intercepted by the channel: 0.14.x: ```elixir defmodule MyApp.RoomChannel do use MyApp.Web, :channel ... def handle_out("new_msg", payload, socket) do push socket, "new_msg", %{role: socket.assigns.role, body: payload["body"]} {:noreply, socket} end end ``` 0.15.0: ```elixir defmodule MyApp.RoomChannel do use MyApp.Web, :channel intercept ["new_msg"] ... def handle_out("new_msg", payload, socket) do push socket, "new_msg", %{role: socket.assigns.role, body: payload["body"]} {:noreply, socket} end end ``` ## Bump your deps Next update your `:phoenix`, `:phoenix_html`, `:phoenix_ecto`, and `:phoenix_live_reload` deps in `mix.exs`: ```elixir def deps do [..., {:phoenix, "~> 0.15"}, {:phoenix_ecto, "~> 0.8"}, {:phoenix_html, "~> 1.4"}, {:phoenix_live_reload, "~> 0.5", only: :dev}, ...] end ``` Next, run `$ mix deps.update --all` ## Grab the latest phoenix.js Upgrade to the latest phoenix.js client by replacing web/static/vendor/phoenix.js with the latest version: https://raw.githubusercontent.com/phoenixframework/phoenix/f6ffac8e040f764bd365325fd1fcf54db06f7749/priv/static/phoenix.js ## Ecto changes (can skip if not using Ecto) We are updating two versions fo Ecto from version 0.12 to 0.14/0.15-dev most of the changes you need to make will be reflected in this section taken from the Ecto Changelog. If you have further issues or compiler errors please check the [Ecto Changelog](https://github.com/elixir-lang/ecto/blob/master/CHANGELOG.md#v0130) for further details. Below is taken from the change for v0.13 backwards incompatible changes. * `Ecto.Repo.update!/2` no longer invokes callbacks if there were no changes, avoiding writing to the database at all (use `:force` to force callback execution) * `Ecto.Repo.transaction/2` is now flattened. This means that multiple transaction calls will no longer use savepoints, instead it will be considered as a single transaction, where a failure in any transaction block will trigger the outmost transaction to rollback, even if failures are rescued. This should only affect users that were explicitly relying on the savepoints. * `:date`, `:time` and `:datetime` were removed in favor of `Ecto.Date`, `Ecto.Time` and `Ecto.DateTime` * `Ecto.Changeset.errors` now return `{"must be less than %{count}", count: 3}` instead of `{"must be less than %{count}", 3}` ## phoenix_pubsub_redis (skip if not using redis adapter) Update your :phoenix_pubsub_redis dep to the latest release: ```elixir def deps do ... {:phoenix_pubsub_redis, "~> 0.2.0"} ... end ```