Best elixir idiom for "var = this || that"?

Hi!

I’m newly learning Elixir and just bumped again a problem that I’m not sure how to write, although I feel like there is probably a neat pattern matching solution, or maybe some better FP syntax.

How would you write the following code?

user = Repo.get_by(User, name: "jon")
unless user do
  user = User |> Ecto.Query.first |> Repo.one
end
user

I feel like there is a better Elixir/FP idiom to write this?

Cheers!

1 Like

What is this code expected to do?

And the code you used on the title would work in elixir as is.

2 Likes

When in doubt, try! :smiley:

user = Repo.get_by(User, name: "jon") || User |> Ecto.Query.first |> Repo.one
3 Likes

Yes sorry if I was not clear. The code works right now, but coming from the ruby world, I was wondering if there was a syntax that would suit Elixir better (aka something for FP).

Seems like not :slight_smile: Thanks for the quick replies!

You might search for first_or_create like in this post

But beware of race condition.

How about:

defmodule Example do
  def get_user(opts), do: User |> Repo.get_by(opts) |> do_get_user()

  defp do_get_user(nil), do: User |> Ecto.Query.first |> Repo.one
  defp do_get_user(user), do: user
end
def get_user  
  case Repo.get_by(User, name: "jon") do
    nil -> User |> Ecto.Query.first |> Repo.one
    repo_user -> repo_user
  end
end

but like the pattern matching one much better…

also be aware of errors if get_by returns more than one record… so maybe refactor this…

4 Likes

Here unless is being used like a statement - which can result in warnings

FP uses expressions, e.g.:

user = 
  case Repo.get_by(User, name: "jon") do
    nil ->
      User |> Ecto.Query.first |> Repo.one
    result ->
      result
  end

which was already shortened to:

user = Repo.get_by(User, name: "jon") || User |> Ecto.Query.first |> Repo.one

which still is an expression.

4 Likes

outlog and peerreynders thanks that’s exactly what I was looking for!

2 Likes

with is also an option, thought I’d personally likely use || here

user = with nil <- Repo.get_by(User, name: "jon"), do: User |> Ecto.Query.first() |> Repo.one()
4 Likes