/
todo_server.ex
99 lines (78 loc) · 1.91 KB
/
todo_server.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
defmodule TodoServer do
use GenServer
def start do
GenServer.start(TodoServer, nil)
end
def add_entry(todo_server, new_entry) do
GenServer.cast(todo_server, {:add_entry, new_entry})
end
def entries(todo_server, date) do
GenServer.call(todo_server, {:entries, date})
end
def init(_) do
{:ok, TodoList.new}
end
def handle_cast({:add_entry, new_entry}, todo_list) do
new_state = TodoList.add_entry(todo_list, new_entry)
{:noreply, new_state}
end
def handle_call({:entries, date}, _, todo_list) do
{
:reply,
TodoList.entries(todo_list, date),
todo_list
}
end
end
defmodule TodoList do
defstruct auto_id: 1, entries: %{}
def new(entries \\ []) do
Enum.reduce(
entries,
%TodoList{},
&add_entry(&2, &1)
)
end
def add_entry(
%TodoList{entries: entries, auto_id: auto_id} = todo_list,
entry
) do
entry = Map.put(entry, :id, auto_id)
new_entries = Map.put(entries, auto_id, entry)
%TodoList{todo_list |
entries: new_entries,
auto_id: auto_id + 1
}
end
def entries(%TodoList{entries: entries}, date) do
entries
|> Stream.filter(fn({_, entry}) ->
entry.date == date
end)
|> Enum.map(fn({_, entry}) ->
entry
end)
end
def update_entry(todo_list, %{} = new_entry) do
update_entry(todo_list, new_entry.id, fn(_) -> new_entry end)
end
def update_entry(
%TodoList{entries: entries} = todo_list,
entry_id,
updater_fun
) do
case entries[entry_id] do
nil -> todo_list
old_entry ->
new_entry = updater_fun.(old_entry)
new_entries = Map.put(entries, new_entry.id, new_entry)
%TodoList{todo_list | entries: new_entries}
end
end
def delete_entry(
%TodoList{entries: entries} = todo_list,
entry_id
) do
%TodoList{todo_list | entries: Map.delete(entries, entry_id)}
end
end