Sirus

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

Sirus

Thanks, here is my problem

it will still bind nil to room

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

kip

ex_cldr Core Team

In your first example,

  • When App.Repo.get(App.Room, 1) returns nil it will still bind nil to room.
  • Then test_fn("good") will return true so that will also pass.
  • Lastly. it will execute IO.inspect(room) and since room == nil you see nil.

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

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:

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement