diff --git a/lib/phoenix/channel.ex b/lib/phoenix/channel.ex index 1bca12c178..1260202a89 100644 --- a/lib/phoenix/channel.ex +++ b/lib/phoenix/channel.ex @@ -20,7 +20,7 @@ defmodule Phoenix.Channel do Any topic coming into the router with the `"room:"` prefix would dispatch to `MyAppWeb.RoomChannel` in the above example. Topics can also be pattern - matched in your channels' `join/3` callback to pluck out the scoped pattern: + matched in your channels' `c:join/3` callback to pluck out the scoped pattern: # handles the special `"lobby"` subtopic def join("room:lobby", _payload, socket) do @@ -40,17 +40,17 @@ defmodule Phoenix.Channel do ## Authorization Clients must join a channel to send and receive PubSub events on that channel. - Your channels must implement a `join/3` callback that authorizes the socket + Your channels must implement a `c:join/3` callback that authorizes the socket for the given topic. For example, you could check if the user is allowed to join that particular room. - To authorize a socket in `join/3`, return `{:ok, socket}`. - To refuse authorization in `join/3`, return `{:error, reply}`. + To authorize a socket in `c:join/3`, return `{:ok, socket}`. + To refuse authorization in `c:join/3`, return `{:error, reply}`. ## Incoming Events After a client has successfully joined a channel, incoming events from the - client are routed through the channel's `handle_in/3` callbacks. Within these + client are routed through the channel's `c:handle_in/3` callbacks. Within these callbacks, you can perform any action. Incoming callbacks must return the `socket` to maintain ephemeral state. @@ -147,7 +147,7 @@ defmodule Phoenix.Channel do - The user's game is ending soon - The IoT device's settings should be updated - For example, you could `push/3` a message to the client in `handle_info/3` + For example, you could `push/3` a message to the client in `c:handle_info/2` after receiving a `PubSub` message relevant to them. alias Phoenix.Socket.Broadcast @@ -167,14 +167,14 @@ defmodule Phoenix.Channel do {:reply, %{val: Game.get_rank(socket.assigns[:user])}, socket} end - Note that in this example, `push/3` is called from `handle_in/3`; in this way + Note that in this example, `push/3` is called from `c:handle_in/3`; in this way you can essentially reply N times to a single message from the client. See `reply/2` for why this may be desirable. ## Intercepting Outgoing Events When an event is broadcasted with `broadcast/3`, each channel subscriber can - choose to intercept the event and have their `handle_out/3` callback triggered. + choose to intercept the event and have their `c:handle_out/3` callback triggered. This allows the event's payload to be customized on a socket by socket basis to append extra information, or conditionally filter the message from being delivered. If the event is not intercepted with `Phoenix.Channel.intercept/1`, @@ -202,7 +202,7 @@ defmodule Phoenix.Channel do ## Terminate - On termination, the channel callback `terminate/2` will be invoked with + On termination, the channel callback `c:terminate/2` will be invoked with the error reason and the socket. If we are terminating because the client left, the reason will be @@ -212,15 +212,15 @@ defmodule Phoenix.Channel do If any of the callbacks return a `:stop` tuple, it will also trigger terminate with the reason given in the tuple. - `terminate/2`, however, won't be invoked in case of errors nor in + `c:terminate/2`, however, won't be invoked in case of errors nor in case of exits. This is the same behaviour as you find in Elixir abstractions like `GenServer` and others. Similar to `GenServer`, - it would also be possible to `:trap_exit` to guarantee that `terminate/2` + it would also be possible to `:trap_exit` to guarantee that `c:terminate/2` is invoked. This practice is not encouraged though. Generally speaking, if you want to clean something up, it is better to monitor your channel process and do the clean up from another process. - All channel callbacks, including `join/3`, are called from within the + All channel callbacks, including `c:join/3`, are called from within the channel process. Therefore, `self()` in any of them returns the PID to be monitored. @@ -502,7 +502,7 @@ defmodule Phoenix.Channel do end @doc """ - Defines which Channel events to intercept for `handle_out/3` callbacks. + Defines which Channel events to intercept for `c:handle_out/3` callbacks. By default, broadcasted events are pushed directly to the client, but intercepting events gives your channel a chance to customize the event @@ -524,7 +524,7 @@ defmodule Phoenix.Channel do {:noreply, socket} end - `handle_out/3` callbacks must return one of: + `c:handle_out/3` callbacks must return one of: {:noreply, Socket.t} | {:noreply, Socket.t, timeout | :hibernate} | @@ -626,7 +626,7 @@ defmodule Phoenix.Channel do correlate that reply with the message you pushed, you'll need to include a unique identifier in the message, track it in the Channel's state, have the client include it in its reply, and examine the ref when the reply comes to - `handle_in/3`. + `c:handle_in/3`. ## Examples @@ -645,13 +645,13 @@ defmodule Phoenix.Channel do @doc """ Replies asynchronously to a socket push. - The usual way of replying to a client's message is to return a tuple from `handle_in/3` + The usual way of replying to a client's message is to return a tuple from `c:handle_in/3` like: {:reply, {status, payload}, socket} But sometimes you need to reply to a push asynchronously - that is, after - your `handle_in/3` callback completes. For example, you might need to perform + your `c:handle_in/3` callback completes. For example, you might need to perform work in another process and reply when it's finished. You can do this by generating a reference to the socket with `socket_ref/1` diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex index 2ebaa8b889..aa98107519 100644 --- a/lib/phoenix/endpoint.ex +++ b/lib/phoenix/endpoint.ex @@ -941,7 +941,7 @@ defmodule Phoenix.Endpoint do endpoint configuration * `:connect_info` - a list of keys that represent data to be copied from - the transport to be made available in the user socket `connect/3` callback. + the transport to be made available in the user socket `c:Phoenix.Socket.connect/3` callback. See the "Connect info" subsection for valid keys ### Connect info diff --git a/lib/phoenix/logger.ex b/lib/phoenix/logger.ex index fea1850e65..2c1727c5d1 100644 --- a/lib/phoenix/logger.ex +++ b/lib/phoenix/logger.ex @@ -103,11 +103,11 @@ defmodule Phoenix.Logger do In some cases you may wish to set the log level dynamically on a per-request basis. To do so, set the `:log` option to - a tuple, `{Mod, Fun, Args}`. The `Plug.Conn.t()` for the + a tuple, `{Mod, Fun, Args}`. The [`Plug.Conn.t()`](`t:Plug.Conn.t/0`) for the request will be prepended to the provided list of arguments. When invoked, your function must return a - [`Logger.level()`](`t:Logger.level()/0`) or `false` to + [`Logger.level()`](`t:Logger.level/0`) or `false` to disable logging for the request. For example, in your Endpoint you might do something like this: diff --git a/lib/phoenix/presence.ex b/lib/phoenix/presence.ex index a936ecee1c..059c08c6e7 100644 --- a/lib/phoenix/presence.ex +++ b/lib/phoenix/presence.ex @@ -130,7 +130,7 @@ defmodule Phoenix.Presence do query |> Repo.all() |> Enum.into(%{}) end - The `fetch/2` function above fetches all users from the database who + The `c:fetch/2` function above fetches all users from the database who have registered presences for the given topic. The presences information is then extended with a `:user` key of the user's information, while maintaining the required `:metas` field from the diff --git a/lib/phoenix/socket.ex b/lib/phoenix/socket.ex index 7b0ec1c518..5a9551ffee 100644 --- a/lib/phoenix/socket.ex +++ b/lib/phoenix/socket.ex @@ -25,11 +25,11 @@ defmodule Phoenix.Socket do Socket handlers are mounted in Endpoints and must define two callbacks: - * `connect/3` - receives the socket params, connection info if any, and + * `c:connect/3` - receives the socket params, connection info if any, and authenticates the connection. Must return a `Phoenix.Socket` struct, often with custom assigns - * `id/1` - receives the socket returned by `connect/3` and returns the + * `c:id/1` - receives the socket returned by `c:connect/3` and returns the id of this connection as a string. The `id` is used to identify socket connections, often to a particular user, allowing us to force disconnections. For sockets requiring no authentication, `nil` can be returned @@ -225,7 +225,7 @@ defmodule Phoenix.Socket do {:ok, Socket.t()} | {:error, term} | :error @doc """ - Shortcut version of `connect/3` which does not receive `connect_info`. + Shortcut version of `c:connect/3` which does not receive `connect_info`. Provided for backwards compatibility. """ diff --git a/lib/phoenix/test/channel_test.ex b/lib/phoenix/test/channel_test.ex index 9897e9ad92..5fbf3119fd 100644 --- a/lib/phoenix/test/channel_test.ex +++ b/lib/phoenix/test/channel_test.ex @@ -38,13 +38,13 @@ defmodule Phoenix.ChannelTest do socket representing communication to be pushed to the server. For example, we can use the `push/3` function in the test - to push messages to the channel (it will invoke `handle_in/3`): + to push messages to the channel (it will invoke `c:Phoenix.Channel.handle_in/3`): push(socket, "my_event", %{"some" => "data"}) Similarly, we can broadcast messages from the test itself on the topic that both test and channel are subscribed to, - triggering `handle_out/3` on the channel: + triggering `c:Phoenix.Channel.handle_out/3` on the channel: broadcast_from(socket, "my_event", %{"some" => "data"}) @@ -75,7 +75,7 @@ defmodule Phoenix.ChannelTest do like writing to the database, and verify those side-effects during their tests. - Imagine the following `handle_in/3` inside a channel: + Imagine the following `c:Phoenix.Channel.handle_in/3` inside a channel: def handle_in("publish", %{"id" => id}, socket) do Repo.get!(Post, id) |> Post.publish() |> Repo.update!() @@ -137,7 +137,7 @@ defmodule Phoenix.ChannelTest do To assert that your channel closes or errors asynchronously, you can monitor the channel process with the tools provided by Elixir, and wait for the `:DOWN` message. - Imagine an implementation of the `handle_info/2` function + Imagine an implementation of the `c:Phoenix.Channel.handle_info/2` function that closes the channel when it receives `:some_message`: def handle_info(:some_message, socket) do @@ -305,7 +305,7 @@ defmodule Phoenix.ChannelTest do Initiates a transport connection for the socket handler. Useful for testing UserSocket authentication. Returns - the result of the handler's `connect/3` callback. + the result of the handler's `c:Phoenix.Socket.connect/3` callback. """ defmacro connect(handler, params, options \\ quote(do: [])) do if endpoint = Module.get_attribute(__CALLER__.module, :endpoint) do @@ -460,7 +460,7 @@ defmodule Phoenix.ChannelTest do @doc """ Pushes a message into the channel. - The triggers the `handle_in/3` callback in the channel. + The triggers the `c:Phoenix.Channel.handle_in/3` callback in the channel. ## Examples @@ -506,7 +506,7 @@ defmodule Phoenix.ChannelTest do Broadcast event from pid to all subscribers of the socket topic. The test process will not receive the published message. This triggers - the `handle_out/3` callback in the channel. + the `c:Phoenix.Channel.handle_out/3` callback in the channel. ## Examples