如何在函数保护条款中测试结构的值?

时间:2015-11-27 14:19:41

标签: elixir phoenix-framework

在这个小卫生功能的Phoenix / Elixir应用程序中,当用户没有输入电子邮件时,我会遇到问题。

我正在使用结构来处理数据。一个简单的卫生功能(现在)只是剥离空白并更新结构(地图)。到目前为止它运作良好,但当字段emailnil时,我收到错误。

** (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

我想是因为这个字段的值在编译时不可用。或类似的东西。

如何解决这个问题?如何测试保护条款中结构的值?

1 个答案:

答案 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)