If `on_mount` is a callback and how to denote it

I find on_mount resembles a callback function. I define it but it’s call is delegated to live_session. But there is no behaviour definition for it. I have two questions.

  • Should it be considered a callback? The way it works.
  • If there is no predefined behaviour, how can I improvise it so that I can @impl true?
# lib/demo_web/auth.ex
def on_mount(:default, params, session, socket) do
  ...
  {:cont, socket}
end

# lib/demo_web/router.ex
live_session :auth, on_mount: Demo.Auth do
  live "/", Home
  ...
end

While it does resemble a behaviour callback, I’d call it something more of a contract. I’m not completely sure why the Phoenix team decided not to make it a behaviour, but I don’t disagree with the decision; it’s not really necessary. I guess they could have defined a Phoenix.LiveView.OnMount behaviour with a single callback, but now you have to cross-link between that and the on_mount documentation, etc. Just doesn’t quite seem worth it.

If you really want to, you can define the behaviour yourself:

defmodule DemoWeb.LiveView.OnMount do
  @callback(...)
end

defmodule DemoWeb.Auth do
  @behaviour DemoWeb.LiveView.OnMount
  ...
end

Nothing changes about the function depending on whether it’s a part of a behaviour, since those are compile-time constructs, so LiveView will call it all the same. But I’m just not sure it’s advisable. I personally just document it.

@doc """
Auth hook called by `Phoenix.LiveView.on_mount/1`.
"""
def on_mount(:default, ...)
1 Like

Having a contract without a behaviour is nothing new. Plug does the same where modules with init/1 and call/2 or any function with arity-2 accepting a conn and options is a valid plug.

1 Like