chan11347
How to put a if else in a function
i want to add a condition in the add_entry to limit the input such like if else in java, any help
server.ex
def add_entry(todo_server, new_entry) do
GenServer.cast(todo_server, {:add_entry, new_entry})
end
@impl GenServer
def handle_cast({:add_entry, new_entry}, {name, todo_list}) do
new_list = Todo.List.add_entry(todo_list, new_entry)
Todo.Database.store(name, new_list)
{:noreply, {name, new_list}}
end
list.ex
def add_entry(todo_list, entry) do
entry = Map.put(entry, :id, todo_list.auto_id)
new_entries = Map.put(todo_list.entries, todo_list.auto_id, entry)
%Todo.List{todo_list | entries: new_entries, auto_id: todo_list.auto_id + 1}
end
Marked As Solved
lucaong
If your map contains keys like :date, :time, etc., then your code above won’t work (because it matches an entry with key :entries).
There are a few possible ways to solve this. First, you could check if any of the entry fields is blank. Remember that maps are Enumerable, so you can enumerate them as a collection of {key, value} with the Enum module:
def add_entry(todo_server, new_entry) do
if Enum.any?(new_entry, fn {_key, value} -> value == nil || value == "" end) do
IO.puts("input cannot be empty!")
else
GenServer.cast(todo_server, {:add_entry, new_entry})
end
end
Instead of printing an output though, it would be better to return an error, so the caller can pattern match easily. Usually, one would return :ok or {:error, reason}:
def add_entry(todo_server, new_entry) do
if Enum.any?(new_entry, fn {_key, value} -> value == nil || value == "" end) do
{:error, "input cannot be empty!"}
else
GenServer.cast(todo_server, {:add_entry, new_entry})
end
end
If the entries always have the same keys, there is a possibly better way to do this: you can use a struct for the entry, instead of a map, to enforce the “shape” of the entry:
defmodule Todo.Server do
defmodule Entry do
@enforce_keys [:date, :time, :title]
defstruct [:date, :time, :title]
end
def add_entry(todo_server, %Entry{date: date, time: time, title: title})
when is_nil(date) or is_nil(time) or is_nil(title) or title == "" do
{:error, "input cannot be empty!"}
end
def add_entry(todo_server, new_entry = %Entry{}) do
GenServer.cast(todo_server, {:add_entry, new_entry})
end
def add_entry(_server, _entry), do: {:error, "Invalid input"}
end
This way, the entry is now a struct that enforces that all of :date, :time, and :value are present. This also mean, though, that the caller of the add_entry function has to pass an Entry struct instead of a map, so it’s your choice whether this is desirable or not.
P.S.:
Unrelated to your question, but you might want to use GenServer.call/3 instead of GenServer.cast/2, even if you don’t need a result. The reason is explained here: https://elixir-lang.org/getting-started/mix-otp/genserver.html#call-cast-or-info
Also Liked
benwilson512
Please always supply errors and code as text. The images are not readable on my screen, and it makes it very hard to suggest edits because I have to retype everything.
lucaong
Yes, now the struct enforces the presence of all the keys. That’s good, because it enforces that an %Entry{} struct without the necessary options simply cannot be created.
That said, if you don’t want that, you can change the struct definition to:
defmodule Entry do
# remove @enforce_keys
defstruct date: nil, time: nil, title: nil
end
Make sure you understand the implications first though:
-
If you use a struct enforcing the keys, you enforce the presence of the keys whenever that struct gets created. That’s generally better, because it’s the developer’s job to make sure that the struct is created with the correct keys. In other words, it’s not a runtime concern. You still validate that the supplied values are not nil, because those values might come from user input, so that is a runtime concern, and you might need to give meaningful error messages to the user.
-
If you do not enforce the keys, when those keys are not set they will default to
nil, and your code will return an error tuple like{:error, "input cannot be empty!"}. This might sound useful, but if it’s the code that builds the struct wrong, an error message to the user won’t be useful.
Last Post!
chan11347
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









