Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reorder the api lesson for more clarity #136

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 49 additions & 45 deletions 04_Mix_Applications/16.5-genserver.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ defmodule MyApp.ApiHandler do
end
```

So now we have completed our GenServer callback implementation. Let's complete the functionality by implementing the `get_poke_request/1` method.
So now we have completed our GenServer callback implementation. Let's complete the functionality by implementing the `get_character_request/1` method.

But first let's add the required dependencies to our `mix.exs` file.

Expand Down Expand Up @@ -163,52 +163,10 @@ defmodule MyApp.ApiHandler do
end
```

We'll start the GenServer process with out supervisor we implemented previously.

The `GenServer.start_link/3` function starts a process linked to the current process. Often times this is used in a Supervision tree.

Let's add our `ApiHandler` module to our supervision tree. Open up our `myapp.ex` file. We will add our ApiHandler as a child in our supervision tree.

Add the following line to our list of children:

Our list of children should now look like this now:

```elixir
def start(_type, _args) do
children = [
{MyApp.Router, []},
{MyApp.ApiHandler, []}
]

opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
```

When our app is started it will start our ApiHandler as a child process.

Now we can call our `get_character_request/1` function from our router.

```elixir
defmodule MyApp.Router do
use Plug.Router

get("/:name") do
query_params = Plug.Conn.fetch_query_params(conn)
name = query_params.params["name"] || 1
character = MyApp.ApiHandler.get_character(name)
conn
|> put_resp_content_type("application/json")
|> send_resp(200, character)
end
end
```

Now we have a non-blocking GenServer that calls an external api in an efficient way.

The last thing we want to call out is that we want to register our GenServer with the Erlang name server.
We'll start the GenServer process with out supervisor we implemented previously.

We will do this with the `start_link/2` function by calling `GenServer.start_link/3` with the name we want to register the GenServer under. Below we are registering the GenServer with the name of the module.
The `GenServer.start_link/3` function starts a process linked to the current process. Often times this is used in a Supervision tree. We'll implement the `start_link/2` function by calling `GenServer.start_link/3` with the name we want to register the GenServer under. Below we are registering the GenServer with the name of the module.

```elixir
defmodule MyApp.ApiHandler do
Expand All @@ -220,6 +178,13 @@ defmodule MyApp.ApiHandler do
end
```

Now that we have our completed ApiHandler, we can call it from the console:

```elixir
iex(2)> MyApp.ApiHandler.get_character(1)
"{\"url\":\"https://anapioficeandfire.com/api/characters/1\",\"name\":\"\",\"gender\":\"Female\",\"culture\":\"Braavosi\",\"born\":\"\",\"died\":\"\",\"titles\":[\"\"],\"aliases\":[\"The Daughter of the Dusk\"],\"father\":\"\",\"mother\":\"\",\"spouse\":\"\",\"allegiances\":[],\"books\":[\"https://anapioficeandfire.com/api/books/5\"],\"povBooks\":[],\"tvSeries\":[\"\"],\"playedBy\":[\"\"]}"
```

The complete `ApiHandler` module looks like this:

```elixir
Expand Down Expand Up @@ -264,3 +229,42 @@ defmodule MyApp.ApiHandler do
end
end
```

Let's add our `ApiHandler` module to our supervision tree. Open up our `myapp.ex` file. We will add our ApiHandler as a child in our supervision tree.

Add the following line to our list of children:

Our list of children should now look like this now:

```elixir
def start(_type, _args) do
children = [
{MyApp.Router, []},
{MyApp.ApiHandler, []}
]

opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
```

When our app is started it will start our ApiHandler as a child process.

Now we can call our `get_character_request/1` function from our router.

```elixir
defmodule MyApp.Router do
use Plug.Router

get("/:name") do
query_params = Plug.Conn.fetch_query_params(conn)
name = query_params.params["name"] || 1
character = MyApp.ApiHandler.get_character(name)
conn
|> put_resp_content_type("application/json")
|> send_resp(200, character)
end
end
```

Now we have a non-blocking GenServer that calls an external api in an efficient way.