Topical.Topic (topical v0.2.2)
This module provides functions for instantiating and manipulating topic state.
The state of a topic is composed of a value, observed by subscribed clients, and also hidden
internal state, which can be used to share state between calls. The value must only be
manipulated by the helper functions (which track the individual updates). The hidden state
can
be modified directly.
This module also contains a macro - use
-ing it sets up a topic server:
defmodule MyApp.Topics.List do
use Topical.Topic, route: ["lists", :list_id]
# Initialise the topic
def init(params) do
list_id = Keyword.fetch!(params, :list_id)
value = %{items: %{}, order: []} # exposed 'value' of the topic
state = %{list_id: list_id} # hidden server state
topic = Topic.new(value, state)
{:ok, topic}
end
# Optionally, handle subscribe
def handle_subscribe(topic, _context) do
{:ok, topic}
end
# Optionally, handle unsubscribe
def handle_unsubscribe(topic, _context) do
{:ok, topic}
end
# Optionally, handle capture
def handle_capture(topic, _context) do
{:ok, topic}
end
# Optionally, handle execution of an action
def handle_execute("add_item", {text}, topic, _context) do
id = Integer.to_string(:erlang.system_time())
# Update the topic by putting the item in 'items', and appending the id to 'order'
topic =
topic
|> Topic.set([:items, id], %{text: text, done: false})
|> Topic.insert([:order], id)
# Return the result (the 'id'), and the updated topic
{:ok, id, topic}
end
# Optionally, handle a notification (an action without a result)
def handle_notify("update_text", {id, text}, topic, _context) do
topic = Topic.set(topic, [:items, id, :text], text)
{:ok, topic}
end
# Optionally, handle Erlang messages
def handle_info({:done, id}, topic) do
topic = Topic.set(topic, [:items, id, :done], true)
{:ok, topic}
end
# Optionally, handle the topic being terminated (e.g., once clients have disconnected)
def terminate(_reason, topic) do
# ...
end
end
Link to this section Summary
Functions
Updates the topic be deleting count
values from the array at the path
, from the index
.
Updates the topic by inserting the specified values
into the array at the path
, at the
index
(or append them to the end, if no index
is specified).
Updates the opic by merging value
into path
.
Instantiates a new instance of a topic.
Updates the topic by setting the value
at the path
.
Updates the topic by unsetting the key
of the object at the path
.
Link to this section Functions
delete(topic, path, index, count \\ 1)
Updates the topic be deleting count
values from the array at the path
, from the index
.
%{foo: %{bar: [1, 2, 3, 4]}}
|> Topic.new()
|> Topic.delete([:foo, :bar], 2)
|> Map.fetch!(:value)
#=> %{foo: %{bar: [1, 2, 4]}}
insert(topic, path, index \\ nil, value)
Updates the topic by inserting the specified values
into the array at the path
, at the
index
(or append them to the end, if no index
is specified).
If value
is a list, all the items will be added (to add a list as a single item, wrap it in a
list).
%{foo: %{bar: [1, 4]}}
|> Topic.new()
|> Topic.insert([:foo, :bar], 1, [2, 3])
|> Map.fetch!(:value)
#=> %{foo: %{bar: [1, 2, 3, 4]}}
merge(topic, path, value)
Updates the opic by merging value
into path
.
%{foo: %{bar: %{a: 1, b: 2}}}
|> Topic.new()
|> Topic.merge([:foo, :bar], %{b: 3, c: 4})
|> Map.fetch!(:value)
#=> %{foo: %{bar: %{a: 1, b: 3, c: 4}}}
new(value, state \\ nil)
Instantiates a new instance of a topic.
value
is the initial value of the client-visible state. state
is the 'hidden' internal state.
set(topic, path, value)
Updates the topic by setting the value
at the path
.
%{foo: %{bar: 2}}
|> Topic.new()
|> Topic.set([:foo, :bar], 3)
|> Map.fetch!(:value)
#=> %{foo: %{bar: 3}}
unset(topic, path, key)
Updates the topic by unsetting the key
of the object at the path
.
%{foo: %{bar: 2}}
|> Topic.new()
|> Topic.unset([:foo], :bar)
|> Map.fetch!(:value)
#=> %{foo: %{}}