In a Phoenix / Elixir app in this little sanitation function I encountered a problem when the user didn't enter an email.
I am using a struct to deal with the data. And a simple sanitation function that (for now) just strips whitespace and updates the struct (map). So far it worked well, but when the field email
is nil
, I get an error.
** (FunctionClauseError) no function clause matching in String.Unicode.strip/1
So I introduced a guard clause to check for this case and then only sanitize the username.
defmodule MyApp.User do
defstruct username: nil, email: nil, password: nil, hashed_password: nil
# Sanitizing input without guard clause
def sanitize_user(user) do
%{user | username: String.strip(user.username), email: String.strip(user.email)}
end
# Sanitizing input with guard clause
def sanitize_user(user) when is_nil(user.email) do
%{user | username: String.strip(user.username)}
end
def sanitize_user(user) when is_binary(user.email) do
%{user | username: String.strip(user.username), email: String.strip(user.email)}
end
end
Now I'm getting an error at compile time:
** (CompileError) web/models/user.ex:54: cannot invoke remote function Access.get/2 inside guard
I guess it is because the value for this field is not available at compile time. Or something like that.
How to solve this? How to test for values of structs in guard clauses?
Your assumptions about the values not being available at compile time is correct. You can however pattern match the values in your map and use them in a guard.
You could write your function like:
def sanitize_user(%MyApp.User{email: nil} = user) do
%{user | username: String.strip(user.username)}
end
def sanitize_user(%MyApp.User{email: email} = user) when is_binary(email) do
%{user | username: String.strip(user.username), email: String.strip(user.email)}
end
You can also match on a map without the User struct if you want to allow a other structs (unlikely in this case) to be passed:
def sanitize_user(%{email: nil} = user)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With