First, clean your deps to avoid phoenix_html conflicts:
$ mix deps.clean phoenix --all
Next, bump phoenix:
{:phoenix, "~> 0.13"},
Update to the latest phoenix_live_relooad 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.
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.
First update your web/static/js/vendor/phoenix.js
file with:
the 0.13 version
Next update your client and server code:
0.12.0:
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
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:
def join("rooms:lobby", _, socket ) do
{:ok, %{messages: Repo.all(Message)}, socket}
end
def join("rooms:" <> _priv_id, _, socket) do
{:error, %{reason: "unauthorized"}
end
let socket = new Phoenix.Socket("/ws")
let chan = socket.chan("rooms:lobby", {})
chan.on("some_event", ...)
chan.join().receive("ok", ({messages}) => {
...
})
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:
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!") )
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
...