在这个小卫生功能的Phoenix / Elixir应用程序中,当用户没有输入电子邮件时,我会遇到问题。
我正在使用结构来处理数据。一个简单的卫生功能(现在)只是剥离空白并更新结构(地图)。到目前为止它运作良好,但当字段email
为nil
时,我收到错误。
** (FunctionClauseError) no function clause matching in String.Unicode.strip/1
所以我引入了一个guard子句来检查这种情况,然后只清理用户名。
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
现在我在编译时遇到错误:
** (CompileError) web/models/user.ex:54: cannot invoke remote function Access.get/2 inside guard
我想是因为这个字段的值在编译时不可用。或类似的东西。
如何解决这个问题?如何测试保护条款中结构的值?
答案 0 :(得分:21)
您对编译时不可用的值的假设是正确的。但是,您可以模式匹配地图中的值,并在守卫中使用它们。
你可以写下你的功能:
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
如果你想允许传递其他结构(在这种情况下不太可能),你也可以在没有User结构的地图上匹配:
def sanitize_user(%{email: nil} = user)