Skip to content

Instantly share code, notes, and snippets.

@aayushmau5
Created June 20, 2022 17:38
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 aayushmau5/2cb00a45aa0d945fbe0bd34f2d8d74dc to your computer and use it in GitHub Desktop.
Save aayushmau5/2cb00a45aa0d945fbe0bd34f2d8d74dc to your computer and use it in GitHub Desktop.
TodoList using GenServer in elixir
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