{"_id":"55833964ea39a939002244bf","project":"54348ec95b10711400c6c445","initVersion":{"_id":"5558c642eb56ae2f00f714fc","version":"0.13.1"},"tags":[],"user":{"_id":"5435b410495d5d0800f3a603","username":"","name":"Lance Halvorsen"},"__v":0,"createdAt":"2015-06-18T21:34:28.281Z","changelog":[],"body":"## Deps\n\nFirst and foremost, bump Phoenix:\n\n    {:phoenix, \"~> 0.13\"},\n    \nUpdate to the latest phoenix_live_reload in `mix.exs`:\n\n    {:phoenix_live_reload, \"~> 0.4\"},\n    \nIf using Ecto, Update to the latest phoenix_ecto in `mix.exs`:\n    \n    {:phoenix_ecto, \"~> 0.4\"},\n    \n    \nThe HTML engine and helpers have been extracted into a `phoenix_html` project. If you are using `*html.eex` templates, simply add the dep to your `mix.exs`:\n\n     {:phoenix_html, \"~> 1.0\"},\n\n\nMake sure to run `mix deps.get` and you should be set on deps.\n\n### Errors on `mix deps.compile`?\nIf you encounter an error like this when you run `mix deps.compile`:\n\n```\n==> phoenix_html\nCompiled lib/phoenix_html/engine.ex\nlib/phoenix_html/link.ex:1: warning: redefining module Phoenix.HTML.Link\nCompiled lib/phoenix_html.ex\nCompiled lib/phoenix_html/link.ex\nlib/phoenix_html/tag.ex:1: warning: redefining module Phoenix.HTML.Tag\nlib/phoenix_html/form_data.ex:17: warning: redefining module Phoenix.HTML.FormData.Plug.Conn\nlib/phoenix_html/safe.ex:1: warning: redefining module Phoenix.HTML.Safe\nCompiled lib/phoenix_html/form_data.ex\nCompiled lib/phoenix_html/tag.ex\nlib/phoenix_html/safe.ex:18: warning: redefining module Phoenix.HTML.Safe.Atom\n \n== Compilation error on file lib/phoenix_html/form.ex ==\n** (CompileError) lib/phoenix_html/form.ex:181: function raw/1 undefined\n    (stdlib) lists.erl:1336: :lists.foreach/2\n    (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6\n \ncould not compile dependency phoenix_html, mix compile failed. You can recompile this dependency with `mix deps.compile phoenix_html` or update it with `mix deps.update phoenix_html`\n```\n\nYou should run `mix deps.clean --all` and then rerun `mix deps.get`. The dependencies should then compile properly.\n\n## Channels\nMinor changes to the server and client have been added. The return signatures of `join/3` have changed. You can now reply directly on join, and you return `{:error, reason}` to refuse joining a channel. The javascript client has also be refactored to avoid the giant \"receive ok\" callback.\n\n0.12.0:\n\n```elixir\ndef join(\"rooms:lobby\", _, socket ) do\n  send(self, :after_join)\n  {:ok, socket}\nend\ndef join(\"rooms:\" <> _priv_id, _, socket) do\n  :ignore\nend\n\ndef handle_info(:after_join, socket) do\n  push socket, \"catchup\", %{messages: Repo.all(Message)};\n  {:noreply, socket}\nend\n```\n\n```javascript\nlet socket = new Phoenix.Socket(\"/ws\")\nlet chan = socket.join(\"rooms:lobby\", {})\nchan.receive(\"ok\", () => {\n  chan.on(\"catchup\", ({messages}) => ...)\n  chan.on(\"some_event\", ...)\n})\n```\n\n0.13.0:\n\n```elixir\ndef join(\"rooms:lobby\", _, socket ) do\n  {:ok, %{messages: Repo.all(Message)}, socket}\nend\ndef join(\"rooms:\" <> _priv_id, _, socket) do\n  {:error, %{reason: \"unauthorized\"}}\nend\n```\n\n```javascript\nlet socket = new Phoenix.Socket(\"/ws\")\nlet chan = socket.chan(\"rooms:lobby\", {})\n\nchan.on(\"some_event\", ...)\n\nchan.join().receive(\"ok\", ({messages}) => {\n  ...\n})\n```\n\n\n### Channel Params\nThe concept of 'channel params' has been added to the clients. Params are what is sent up as the second argument on join/3, but we have given them a clear name and you can now modify the params which will be passed up on every reconnect, ie imagine a game where we have a game lobby and private game rooms that require information passed to the lobby. We can store a passed player ID and token on the `chan.params` which will be passed back up to the server on reconnects:\n\n\n```javascript\nlet chan = socket.chan(\"lobby\", {})\n\nchan.join().receive(\"ok\", ({player_id, player_token}) => {\n  chan.params[\"player_id\"] = player_id \n  chan.params[\"player_token\"] = player_token\n})\n\n...\n\nlet gameChan = socket.chan(\"games:\" + game_id, {\n  player_id: chan.params.player_id, \n  player_token: chan.params.player_token\n})\n\ngameChan.join().receive(\"ok\", () => console.log(\"Welcome to the game!\") )\n```\n\n```elixir\ndefmodule MyApp.LobbyChannel do\n  ...\n  def join(\"lobby\", %{}, socket) do\n    {player_id, player_token} = something_that_gets_these_things()\n    {:ok, %{player_id: player_id, player_token: player_token}, socket}\n  end\n  def join(\"lobby\", %{\"player_id\" => player_id, \"player_token\" => player_token}, socket) do\n    # we've already issued a player_id, client is reconnecting with it, verify the token\n    {:ok, %{player_id: player_id, player_token: player_token}, socket}\n  end\n  \n  ...\n\n\ndefmodule MyApp.GameChannel do\n  ...\n  def join(\"games:\" <> game_id, %{\"player_id\" => player_id, \"player_token\" => player_token}, socket) do\n    # verify player_token\n    {:ok, socket}\n  end\n  \n  ...\n```","slug":"upgrading-from-v0120-to-v0130","title":"Upgrading from v0.12.0 to v0.13.0"}

Upgrading from v0.12.0 to v0.13.0


## Deps First and foremost, bump Phoenix: {:phoenix, "~> 0.13"}, Update to the latest phoenix_live_reload in `mix.exs`: {:phoenix_live_reload, "~> 0.4"}, If using Ecto, Update to the latest phoenix_ecto in `mix.exs`: {:phoenix_ecto, "~> 0.4"}, The HTML engine and helpers have been extracted into a `phoenix_html` project. If you are using `*html.eex` templates, simply add the dep to your `mix.exs`: {:phoenix_html, "~> 1.0"}, Make sure to run `mix deps.get` and you should be set on deps. ### Errors on `mix deps.compile`? If you encounter an error like this when you run `mix deps.compile`: ``` ==> phoenix_html Compiled lib/phoenix_html/engine.ex lib/phoenix_html/link.ex:1: warning: redefining module Phoenix.HTML.Link Compiled lib/phoenix_html.ex Compiled lib/phoenix_html/link.ex lib/phoenix_html/tag.ex:1: warning: redefining module Phoenix.HTML.Tag lib/phoenix_html/form_data.ex:17: warning: redefining module Phoenix.HTML.FormData.Plug.Conn lib/phoenix_html/safe.ex:1: warning: redefining module Phoenix.HTML.Safe Compiled lib/phoenix_html/form_data.ex Compiled lib/phoenix_html/tag.ex lib/phoenix_html/safe.ex:18: warning: redefining module Phoenix.HTML.Safe.Atom == Compilation error on file lib/phoenix_html/form.ex == ** (CompileError) lib/phoenix_html/form.ex:181: function raw/1 undefined (stdlib) lists.erl:1336: :lists.foreach/2 (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6 could not compile dependency phoenix_html, mix compile failed. You can recompile this dependency with `mix deps.compile phoenix_html` or update it with `mix deps.update phoenix_html` ``` You should run `mix deps.clean --all` and then rerun `mix deps.get`. The dependencies should then compile properly. ## Channels Minor changes to the server and client have been added. The return signatures of `join/3` have changed. You can now reply directly on join, and you return `{:error, reason}` to refuse joining a channel. The javascript client has also be refactored to avoid the giant "receive ok" callback. 0.12.0: ```elixir def join("rooms:lobby", _, socket ) do send(self, :after_join) {:ok, socket} end def join("rooms:" <> _priv_id, _, socket) do :ignore end def handle_info(:after_join, socket) do push socket, "catchup", %{messages: Repo.all(Message)}; {:noreply, socket} end ``` ```javascript let socket = new Phoenix.Socket("/ws") let chan = socket.join("rooms:lobby", {}) chan.receive("ok", () => { chan.on("catchup", ({messages}) => ...) chan.on("some_event", ...) }) ``` 0.13.0: ```elixir def join("rooms:lobby", _, socket ) do {:ok, %{messages: Repo.all(Message)}, socket} end def join("rooms:" <> _priv_id, _, socket) do {:error, %{reason: "unauthorized"}} end ``` ```javascript let socket = new Phoenix.Socket("/ws") let chan = socket.chan("rooms:lobby", {}) chan.on("some_event", ...) chan.join().receive("ok", ({messages}) => { ... }) ``` ### Channel Params The concept of 'channel params' has been added to the clients. Params are what is sent up as the second argument on join/3, but we have given them a clear name and you can now modify the params which will be passed up on every reconnect, ie imagine a game where we have a game lobby and private game rooms that require information passed to the lobby. We can store a passed player ID and token on the `chan.params` which will be passed back up to the server on reconnects: ```javascript let chan = socket.chan("lobby", {}) chan.join().receive("ok", ({player_id, player_token}) => { chan.params["player_id"] = player_id chan.params["player_token"] = player_token }) ... let gameChan = socket.chan("games:" + game_id, { player_id: chan.params.player_id, player_token: chan.params.player_token }) gameChan.join().receive("ok", () => console.log("Welcome to the game!") ) ``` ```elixir defmodule MyApp.LobbyChannel do ... def join("lobby", %{}, socket) do {player_id, player_token} = something_that_gets_these_things() {:ok, %{player_id: player_id, player_token: player_token}, socket} end def join("lobby", %{"player_id" => player_id, "player_token" => player_token}, socket) do # we've already issued a player_id, client is reconnecting with it, verify the token {:ok, %{player_id: player_id, player_token: player_token}, socket} end ... defmodule MyApp.GameChannel do ... def join("games:" <> game_id, %{"player_id" => player_id, "player_token" => player_token}, socket) do # verify player_token {:ok, socket} end ... ```