diff --git a/README.md b/README.md
index 8d354942..71301e2a 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,8 @@ and **_understand_** all the concepts in **10 minutes** or _less_! ๐
- [Add More Tests!](#add-more-tests)
- [Bonus Level: Use a `LiveView Component` (Optional)](#bonus-level-use-a-liveview-component-optional)
- [Create a `LiveView Component`](#create-a-liveview-component)
- - [Moving state out of the LiveViews](#moving-state-out-of-the-liveviews)
+ - [Moving state out of the `LiveView`](#moving-state-out-of-the-liveview)
+ - [Update the Tests for `GenServer` State](#update-the-tests-for-genserver-state)
- [How many people are using the Counter?](#how-many-people-are-using-the-counter)
- [More Tests!](#more-tests)
- [_Done_! ๐](#done-)
@@ -1192,9 +1193,8 @@ update the `render/1` function to:
```
-
> ๐ Your `counter_component.ex` should look like this:
-[`lib/counter_web/live/counter_component.ex`]()
+[`lib/counter_web/live/counter_component.ex`](https://github.com/dwyl/phoenix-liveview-counter-tutorial/blob/92a25e41d52be7bbfd430b92181540806af64baa/lib/counter_web/live/counter_component.ex)
The component's has an identical
[`render/1`](https://github.com/dwyl/phoenix-liveview-counter-tutorial/blob/33e0e47fd379e1314dcba6509d214c9468632c77/lib/counter_web/live/counter.ex#L27-L34)
@@ -1208,7 +1208,7 @@ Re-run the `counter` App
using `mix phx.server`
and confirm everything still works:
-![phoenix-liveview-counter-42](https://user-images.githubusercontent.com/194400/76267885-14985280-6264-11ea-8e6d-52d5166aacd9.gif)
+![phoenix-liveview-counter-component](https://github.com/dwyl/phoenix-liveview-counter-tutorial/assets/194400/7026e461-003d-4033-a0ea-c80b55494fa5)
The tests all still pass and we have 100% coverage:
@@ -1231,9 +1231,10 @@ COV FILE LINES RELEVANT MISSED
----------------
```
+
-## Moving state out of the LiveViews
+## Moving state out of the `LiveView`
With this implementation you may have noticed that when we open a new browser
window the count is always zero. As soon as we click plus or minus it adjusts
@@ -1241,33 +1242,35 @@ and all the views get back in line. This is because the state is replicated
across LiveView instances and coordinated via pub-sub. If the state was big
and complicated this would get wasteful in resources and hard to manage.
-Generally it is good practice to identify _shared state_ and to manage that in
+Generally it is good practice
+to identify _shared state_
+and to manage that in
a single location.
-The Elixir way of managing state is the
-[GenServer](https://hexdocs.pm/elixir/GenServer.html), using PubSub to update
-the LiveViews about changes. This allows the LiveViews to focus on user specific
-state, separating concerns; making the application both more efficient
+The `Elixir` way of managing state is the
+[`GenServer`](https://hexdocs.pm/elixir/GenServer.html),
+using `PubSub` to update
+the `LiveView` about changes.
+This allows the `LiveViews`
+to focus on specific state,
+separating concerns;
+making the application both more efficient
(hopefully) and easier to reason about and debug.
-We are now going to start making use of the lib/live_view_counter directory! The
-[Phoenix docs](https://hexdocs.pm/phoenix/directory_structure.html#content) says
-that this holds "all of your business domain". For us this is the current count,
-along with the incr and decr methods.
-Create a file with the path `lib/live_view_counter/counter.ex` and add the following:
+Create a file with the path:
+`lib/counter_web/live/counter_state.ex`
+and add the following:
```elixir
-defmodule LiveViewCounter.Count do
+defmodule Counter.Count do
use GenServer
-
alias Phoenix.PubSub
-
@name :count_server
@start_value 0
- # ------- External API (runs in client process) -------
+ # External API (runs in client process)
def topic do
"count"
@@ -1293,7 +1296,7 @@ defmodule LiveViewCounter.Count do
{:ok, start_count}
end
- # ------- Implementation (Runs in GenServer process) -------
+ # Implementation (Runs in GenServer process)
def handle_call(:current, _from, count) do
{:reply, count, count}
@@ -1309,58 +1312,59 @@ defmodule LiveViewCounter.Count do
defp make_change(count, change) do
new_count = count + change
- PubSub.broadcast(LiveViewCounter.PubSub, topic(), {:count, new_count})
+ PubSub.broadcast(Counter.PubSub, topic(), {:count, new_count})
{:reply, new_count, new_count}
end
end
```
-The GenServer runs in its own process. Other parts of the application invoke
+The `GenServer` runs in its own process.
+Other parts of the application invoke
the API in their own process, these calls are forwarded to the `handle_call`
-functions in the GenServer process where they are processed serially.
+functions in the `GenServer` process where they are processed serially.
-We have also moved the PubSub publication here as well.
+We have also moved the `PubSub` publication here as well.
We are also going to need to tell the Application that it now has some business
logic; we do this in the `start/2` function in the
-`lib/live_view_counter/application.ex file`.
+`lib/counter/application.ex` file.
```diff
def start(_type, _args) do
children = [
# Start the App State
-+ LiveViewCounter.Count,
++ Counter.Count,
# Start the Telemetry supervisor
CounterWeb.Telemetry,
# Start the PubSub system
- {Phoenix.PubSub, name: LiveViewCounter.PubSub},
+ {Phoenix.PubSub, name: Counter.PubSub},
# Start the Endpoint (http/https)
CounterWeb.Endpoint
- # Start a worker by calling: LiveViewCounter.Worker.start_link(arg)
- # {LiveViewCounter.Worker, arg}
+ # Start a worker by calling: Counter.Worker.start_link(arg)
+ # {Counter.Worker, arg}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
- opts = [strategy: :one_for_one, name: LiveViewCounter.Supervisor]
+ opts = [strategy: :one_for_one, name: Counter.Supervisor]
Supervisor.start_link(children, opts)
end
...
```
-Finally, we are going to have to make some changes to the LiveView itself,
+Finally, we need make some changes to the `LiveView` itself,
it now has less to do!
```elixir
defmodule CounterWeb.Counter do
use CounterWeb, :live_view
- alias LiveViewCounter.Count
+ alias Counter.Count
alias Phoenix.PubSub
@topic Count.topic
def mount(_params, _session, socket) do
- PubSub.subscribe(LiveViewCounter.PubSub, @topic)
+ PubSub.subscribe(Counter.PubSub, @topic)
{:ok, assign(socket, val: Count.current()) }
end
@@ -1389,10 +1393,112 @@ defmodule CounterWeb.Counter do
end
```
-What is happening now is that the initial state is being retrieved from the
-shared Application GenServer process and the updates are being forwarded there
-via its API. Finally, the Gen Server Handlers publish the new state to all the
-active LiveViews.
+The initial state is retrieved from the
+shared Application `GenServer`` process
+and the updates are being forwarded there
+via its API.
+Finally, the `GenServer`
+to all the active `LiveView` clients.
+
+### Update the Tests for `GenServer` State
+
+Given that the `counter.ex` is now using the `GenServer` State,
+two of the tests now fail because the count is not correct.
+
+```sh
+mix t
+
+Generated counter app
+.....
+
+ 1) test connected mount (CounterWeb.CounterTest)
+ test/counter_web/live/counter_test.exs:6
+ Assertion with =~ failed
+ code: assert html =~ "Counter: 0"
+ left: "