Jered
Jered

Reputation: 169

elixir: advanced `cond` operation - best practice?

I have a complex use case of cond I'm curious if this is the best way to do it.

The code below basically attempts to match up a customer with an existing record.

I need the code to stop checking once a query permutation returns any rows.

customers = cond do
  (c = CustomerRepo.findExactNameAndDob(store_id, firstname, lastname, dob)) |> length > 0 -> c
  (c = CustomerRepo.findExactNameAndMobile(store_id, firstname, lastname, phone)) |> length > 0 -> c
  (c = CustomerRepo.findExactNameAndEmail(store_id, firstname, lastname, email)) |> length > 0 -> c
  (c = CustomerRepo.findExactNameAndLocation(store_id, firstname, lastname, address, postcode)) |> length > 0 -> c

  true -> nil
end

There's many more queries, I've trimmed this a bit. Don't focus on the business logic, I just want to clean up this condition.

Upvotes: 1

Views: 127

Answers (1)

Dogbert
Dogbert

Reputation: 222158

We can make use of the fact that the function is in the same module and the first three arguments are fixed to simplify this using Enum.reduce_while/3:

[
  {:findExactNameAndDob, [dob]},
  {:findExactNameAndMobile, [phone]},
  {:findExactNameAndEmail, [email]},
  {:findExactNameAndLocation, [address, postcode]}
]
|> Enum.reduce_while(nil, fn {func, args}, nil ->
  case apply(CustomerRepo, func, [store_id, firstname, lastname] ++ args) do
    [] -> {:cont, nil}
    customers -> {:halt, customers}
  end
end)

This should make the code much simpler since you say you have many more such clauses in the actual code.

Edit: There's a simpler way assuming the success value is not nil or false (here it's always a list so it's fine) using Enum.find_value/2:

[
  {:findExactNameAndDob, [dob]},
  {:findExactNameAndMobile, [phone]},
  {:findExactNameAndEmail, [email]},
  {:findExactNameAndLocation, [address, postcode]}
]
|> Enum.find_value(fn {func, args} ->
  case apply(CustomerRepo, func, [store_id, firstname, lastname] ++ args) do
    [] -> false
    customers -> customers
  end
end)

Upvotes: 1

Related Questions