Skip to content

Commit a2fe3c7

Browse files
author
Aleksei Matiushkin
committed
Allow name: keyword param in call to use Scenic.{Scene,component} to create named process
1 parent 2371ccc commit a2fe3c7

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

lib/scenic/component.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ defmodule Scenic.Component do
4949
should do some basic validation that the data being set up is valid, then provide
5050
feedback if it isn't.
5151
52+
## Optional: Named Component
53+
54+
Whether you override one or more message handlers, like `handle_info/2`,
55+
you might want to use registered name as
56+
[`Process.dest()`](https://hexdocs.pm/elixir/Process.html?#t:dest/0).
57+
For this to be possible, you might pass `name:` keyword argument in a call
58+
to `use Scenic.Component`.
59+
60+
use Scenic.Component, name: __MODULE__
61+
62+
Once passed, it limits the usage of this particular component to
63+
a single instance, because two processes cannot be registered under the same name.
64+
5265
## Optional: No Children
5366
5467
There is an optimization you can use. If you know for certain that your component

lib/scenic/scene.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ defmodule Scenic.Scene do
109109
immediate control. You update that graph by calling `push_graph`
110110
again.
111111
112-
**Note: ** The use of `push_graph` when returning from a scene update
112+
**Note: ** The use of `push_graph` when returning from a scene update
113113
has been deprecated. The use of `push: graph` in the return value is preferred.
114114
115115
This does mean you could maintain two separate graphs
@@ -664,6 +664,12 @@ defmodule Scenic.Scene do
664664
# child spec that really starts up scene, with this module as an option
665665
@doc false
666666
def child_spec({args, opts}) when is_list(opts) do
667+
opts =
668+
case unquote(using_opts)[:name] do
669+
mod when is_atom(mod) -> Keyword.put_new(opts, :name, mod)
670+
_ -> opts
671+
end
672+
667673
%{
668674
id: make_ref(),
669675
start: {Scenic.Scene, :start_link, [__MODULE__, args, opts]},
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
defmodule Scenic.Component.CustomMessageTest do
2+
use ExUnit.Case
3+
4+
setup do
5+
ast =
6+
quote do
7+
use Scenic.Component, name: C
8+
9+
@graph Scenic.Graph.build()
10+
11+
@impl Scenic.Scene
12+
def handle_info({:ping, pid}, state) do
13+
send(pid, :pong)
14+
{:noreply, state}
15+
end
16+
17+
@impl Scenic.Scene
18+
def handle_info({:DOWN, _, :process, _, _}, state),
19+
do: {:noreply, state}
20+
21+
@impl Scenic.Scene
22+
def init(_args, _opts \\ []) do
23+
graph = @graph
24+
25+
state = %{
26+
graph: graph
27+
}
28+
29+
{:ok, state, push: graph}
30+
end
31+
32+
@impl Scenic.Component
33+
def verify(data), do: {:ok, data}
34+
end
35+
36+
{:module, component, _, _} = Module.create(C, ast, Macro.Env.location(__ENV__))
37+
38+
on_exit(fn ->
39+
:code.purge(C)
40+
:code.delete(C)
41+
end)
42+
43+
[component: component]
44+
end
45+
46+
test "send message to named component", %{component: component} do
47+
{:ok, sup} = Supervisor.start_link([{C, {[], []}}], strategy: :one_for_one)
48+
49+
send(component, {:ping, self()})
50+
assert_receive(:pong, 200)
51+
Supervisor.stop(sup)
52+
end
53+
end

0 commit comments

Comments
 (0)