Sorcery.LiveHelpers behaviour (sorcery v0.4.14)
Functions for combining Sorcery and LiveViews
Summary
Callbacks
Wherever you keep your handle_info functions, put this:
Puts a :sorcery key in socket.assigns, with a bunch of stuff used behind the scenes by Sorcery.
Get a list of entities at the given portal/lvar You probably want to use this inside heex
Creates a portal between the LiveView and the PortalServer, using the given arguments.
Functions
Get a list of entities at the given lvar.
Types
hook()
@type hook() :: (ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket, map() -> {:ok, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket} | {:error, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket})
socket_type()
Callbacks
handle_sorcery({}, atom)
@callback handle_sorcery( {:sorcery, map()}, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket ) :: {:noreply, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket}
handle_sorcery({}, atom, list)
@callback handle_sorcery( {:sorcery, map()}, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket, [ hook() ] ) :: {:noreply, ElixirLS.LanguageServer.Plugins.Phoenix.LiveView.Socket}
Wherever you keep your handle_info functions, put this:
defmodule MyModule do
use Sorcery.LiveHelpers
def handle_info({:sorcery, _} = msg, socket), do: handle_sorcery(msg, socket)
# If you have any other handle_info's, put them BELOW
end
By doing this, the socket will automatically communicate with the rest of Sorcery. For example whenever we receive new data about a portal, this is where it happens.
You can optionally pass in an options argument, which is handy for writing your own middleware.
defmodule SomeModule do
def my_func(socket, msg), {:ok, socket}
def another_func(socket, msg), {:ok, socket}
end
defmodule MyModule do
use Sorcery.LiveHelpers
def handle_info({:sorcery, _} = msg, socket), do: handle_sorcery(msg, socket,
hook_before: [&SomeModule.my_func/2],
hook_after: [&SomeModule.another_func/2],
)
end
Note that every middleware function must return a tuple. Either {:ok, socket} or {:error, socket}
In this case, every time the LiveView receives a sorcery message, it will:
- Call all the functions in hook_before, in order
- Do some sorcery magic behind the scenes
- Call all the functions in hook_after, in order
Often in step 2, it will send a message to the parent PortalServer. Then 3 is called before we get a response. "After" means after you SEND the message, not after you RECEIVE a response. So this could take some advanced understanding of how Sorcery works, or a lot of fiddling and pattern matching on msg[:command]
initialize_sorcery(socket, body)
@callback initialize_sorcery( socket :: socket_type(), body :: %{ optional(:sorcery_module) => module(), optional(:args) => map(), optional(:store_adapter) => module() } ) :: socket_type()
Puts a :sorcery key in socket.assigns, with a bunch of stuff used behind the scenes by Sorcery.
This is mandatory, before you can spawn any portals
You must pass in the sorcery_module. If you used the generator, it'll just be Src.
Examples
iex> body = %{sorcery_module: Src}
iex> socket = initialize_sorcery(socket, body)
portal_view(sorcery_config, portal_name, lvar)
Get a list of entities at the given portal/lvar You probably want to use this inside heex
<% players = portal_view(@sorcery, :my_portal, "?all_players") %>
spawn_portal(socket, body, opts)
@callback spawn_portal( socket :: socket_type(), body :: %{ portal_server: module(), portal_name: atom(), query_module: module(), query_args: map() }, opts :: [] ) :: socket_type()
Creates a portal between the LiveView and the PortalServer, using the given arguments.
Takes the socket, returns it unchanged.
Examples
iex> body = %{portal_server: Postgres, portal_name: :my_portal, query_module: MyQuery, query_args: %{player_id: 1}}
iex> socket = spawn_portal(socket, body)
Functions
Get a list of entities at the given lvar.
If this lvar only exists in ONE portal, you can leave out the portal_name, just know that it might be imperceptibly slower since the function needs to iterate over all portals until it finds one with that lvar..
<% players = portal_view(@sorcery, :my_portal, "?all_players") %>