Sirus
Control structure `with else` problem
I am playing with elixir, phoenix and ecto. And ran into trouble.
Repo.get return nil because Room table is empty when test start. But else block with nil pattern don’t work.
My code:
test "unexisted room" do
with room <- App.Repo.get(App.Room, 1),
true <- test_fn("good") do
IO.inspect(room)
else
nil -> IO.puts("Room does not exist")
false -> IO.puts("Not good")
_ -> IO.puts("error")
end
end
defp test_fn(good?) do
case good? do
"good" -> true
_ -> false
end
end
result mix.test:
nil.
If i change true <- test_fn("some not good") it return false and else block work fine
result mix.test:
Not good.
Then for test i add nil case in test_fn and add call test_fn in with block
Code:
test "unexisted room" do
with room <- App.Repo.get(App.Room, 1),
true <- test_fn(nil),
true <- test_fn("false") do
IO.inspect(room)
else
nil -> IO.puts("Room does not exist")
false -> IO.puts("Not good")
_ -> IO.puts("error")
end
end
defp test_fn(good?) do
case good? do
"good" -> true
nil -> nil
_ -> false
end
end
result mix.test:
Room does not exist.
Why with else don’t work with ecto repo?
Marked As Solved
Sirus
Thanks, here is my problem
it will still bind
niltoroom
My solution
with %App.Room{} = room <- App.Repo.get(App.Room, 1),
true <- test_fn("good") do
IO.inspect(room)
else
nil -> IO.puts("Room does not exist")
false -> IO.puts("Not good")
_ -> IO.puts("error")
end
Also Liked
kip
In your first example,
- When
App.Repo.get(App.Room, 1)returnsnilit will still bindniltoroom. - Then
test_fn("good")will returntrueso that will also pass. - Lastly. it will execute
IO.inspect(room)and sinceroom == nilyou seenil.
From that explanation I think you can work out the second example. You might find some value in with room when not is_nil(room) <- App.Repo.get(App.Room, 1).
joey_the_snake
If the else behaviour changes depending on the type of failure, it is generally considered clearer to put those behaviours inside of their own functions and then use those functions inside the with statement.
For example, your code can be refactored to this:
with %App.Room{} = room <- get_room(1),
true <- test_fn("good") do
IO.inspect(room)
end
defp get_room(room_id) do
case App.Repo.get(room_id) do
nil ->
IO.puts("Room does not exist")
nil
room ->
room
end
end
defp test_fn(good?) do
case good? do
"good" ->
true
_ ->
IO.puts("Not good")
false
end
end
or this
with {:ok, room} <- get_room(1),
{:ok, true} <- test_fn("good") do
IO.inspect(room)
else
{:error, reason} -> IO.puts(reason)
end
defp get_room(room_id) do
case App.Repo.get(room_id) do
nil ->
{:error, "Room does not exist"}
room ->
{:ok, room}
end
end
defp test_fn(good?) do
case good? do
"good" ->
{:ok, true}
_ ->
{:error, "Not Good"}
end
end
Some references:
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
- #api
- #forms
- #metaprogramming
- #security
- #hex









