Created
June 20, 2022 17:38
-
-
Save aayushmau5/2cb00a45aa0d945fbe0bd34f2d8d74dc to your computer and use it in GitHub Desktop.
TodoList using GenServer in elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule TodoList do | |
defstruct auto_id: 1, entries: %{} | |
use GenServer | |
def start do | |
GenServer.start(TodoList, nil) | |
end | |
def add_entry(pid, entry) do | |
GenServer.cast(pid, {:put, entry}) | |
end | |
def entries(pid, date) do | |
GenServer.call(pid, {:get, date}) | |
end | |
def update_entry(pid, entry_id, updater_fun) do | |
GenServer.cast(pid, {:update, entry_id, updater_fun}) | |
end | |
def delete_entry(pid, entry_id) do | |
GenServer.cast(pid, {:delete, entry_id}) | |
end | |
@impl GenServer | |
def init(_) do | |
{:ok, %TodoList{}} | |
end | |
@impl GenServer | |
def handle_cast({:put, entry}, state) do | |
entry = Map.put(entry, :id, state.auto_id) | |
new_entries = Map.put(state.entries, state.auto_id, entry) | |
{:noreply, | |
%TodoList{ | |
auto_id: state.auto_id + 1, | |
entries: new_entries | |
}} | |
end | |
@impl GenServer | |
def handle_cast({:update, entry_id, updater_fun}, state) do | |
new_state = | |
case Map.fetch(state.entries, entry_id) do | |
:error -> | |
state | |
{:ok, old_entry} -> | |
old_entry_id = old_entry.id | |
new_entry = %{id: ^old_entry_id} = updater_fun.(old_entry) | |
new_entries = Map.put(state.entries, new_entry.id, new_entry) | |
%TodoList{state | entries: new_entries} | |
end | |
{:noreply, new_state} | |
end | |
@impl GenServer | |
def handle_cast({:delete, entry_id}, state) do | |
entries = Map.delete(state.entries, entry_id) | |
{ | |
:noreply, | |
%TodoList{ | |
state | |
| entries: entries | |
} | |
} | |
end | |
@impl GenServer | |
def handle_call({:get, date}, _, state) do | |
entries = | |
state.entries | |
|> Stream.filter(fn {_, entry} -> entry.date == date end) | |
|> Enum.map(fn {_, entry} -> entry end) | |
{:reply, entries, state} | |
end | |
end | |
{:ok, pid} = TodoList.start() | |
TodoList.add_entry(pid, %{date: ~D[2022-07-10], title: "Movies"}) | |
TodoList.add_entry(pid, %{date: ~D[2022-07-11], title: "Dentist"}) | |
TodoList.add_entry(pid, %{date: ~D[2022-07-11], title: "Team meeting"}) | |
IO.puts(inspect(TodoList.entries(pid, ~D[2022-07-10]))) | |
IO.puts(inspect(TodoList.entries(pid, ~D[2022-07-11]))) | |
TodoList.update_entry(pid, 2, fn entry -> | |
new_entry = Map.update(entry, :title, nil, fn _ -> "hello, world" end) | |
new_entry | |
end) | |
IO.puts(inspect(TodoList.entries(pid, ~D[2022-07-11]))) | |
TodoList.delete_entry(pid, 2) | |
IO.puts(inspect(TodoList.entries(pid, ~D[2022-07-11]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment