Skip to content

Instantly share code, notes, and snippets.

@Preen
Created April 11, 2017 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Preen/0438aa748f6b4c7827787751654192f8 to your computer and use it in GitHub Desktop.
Save Preen/0438aa748f6b4c7827787751654192f8 to your computer and use it in GitHub Desktop.
defmodule Todo.Application do
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
# Define workers and child supervisors to be supervised
children = [
# Starts a worker by calling: Todo.Worker.start_link(arg1, arg2, arg3)
# worker(Todo.Worker, [arg1, arg2, arg3]),
#
supervisor(Todo.Server, [])
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Todo.Supervisor]
Supervisor.start_link(children, opts)
end
end
defmodule Todo.List do
use GenServer
def name(list) do
GenServer.call(list, :name)
end
def items(list) do
GenServer.call(list, :items)
end
def add(list, item) do
GenServer.cast(list, {:add, item})
end
def update(list, item) do
GenServer.cast(list, {:update, item})
end
###
# GenServer API
###
def start_link(name) do
GenServer.start_link(__MODULE__, name)
end
def init(name) do
state = %{name: name, items: []}
{:ok, state}
end
def handle_call(:name, _from, state) do
{:reply, state.name, state}
end
def handle_call(:items, _from, state) do
{:reply, state.items, state}
end
def handle_cast({:add, item}, state) do
state = %{state | items: [item | state.items]}
{:noreply, state}
end
def handle_cast({:update, item}, state) do
index = Enum.find_index(state.items, &(&1.id == item.id))
items = List.replace_at(state.items, index, item)
state = %{state | items: items}
{:noreply, state}
end
end
defmodule Todo.Item do
defstruct id: nil,
description: nil,
completed: false
def new(description) do
%__MODULE__{
id: :rand.uniform(1_000_000_000),
description: description
}
end
end
defmodule Todo.Server do
use Supervisor
def add_list(name) do
Supervisor.start_child(__MODULE__, [name])
end
def find_list(name) do
Enum.find lists(), fn(child) ->
Todo.List.name(child) == name
end
end
def lists do
__MODULE__
|> Supervisor.which_children
|> Enum.map(fn({_, child, _ , _}) -> child end )
end
###
# Supervisor API
###
def start_link do
Supervisor.start_link(__MODULE__, [], name: __MODULE__)
end
def init(_) do
children = [
worker(Todo.List, [], restart: :transient)
]
supervise(children, strategy: :simple_one_for_one)
end
end
# Tests
defmodule Todo.ServerTest do
use ExUnit.Case
alias Todo.Server
test ".add_list adds a new supervised todo list" do
Server.add_list("home")
Server.add_list("Work")
counts = Supervisor.count_children(Server)
assert counts.active == 2
end
test ".find_list gets a list by its name" do
Server.add_list("find-by-name")
list = Server.find_list("find-by-name")
assert is_pid(list)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment