凤凰:上下文中的模式匹配参数(原子和字符串)

时间:2017-10-05 14:50:35

标签: elixir phoenix-framework

我有以下功能定义,我试图找到一种方法来简化参数,使它们全部均匀。

  def update_user(%User{} = user, %{password: _} = attrs) do
    attrs = Map.put(attrs, :password_reset_token, nil)
    update_user(user, attrs, &User.password_changeset/2)
  end

  def update_user(%User{} = user, %{password_reset_token: _} = attrs), do:
    update_user(user, attrs, &User.password_reset_changeset/2)

  def update_user(user, attrs), do:
    update_user(user, attrs, &User.changeset/2)

  def update_user(user, attrs, changeset) do
    user
    |> changeset.(attrs)
    |> Repo.update()
  end

程序员可能会把这个弄得一团糟,通过传递一个带有字符串键的地图(例如%{"password" => value})并且它与update_user/2匹配。那么也许我应该更新这些功能的参数?或者使用update_user(user, attrs)上的警卫与w %{"password" => value}不匹配?

与以下对比,从控制器函数(def create(conn, params))直接获取参数:

  def authenticate_user(%{"email" => email, "access_token" => _}) do
    case get_by(%{email: email}) do
      %User{} = user ->
        {:ok, user}
      nil ->
        {:error, :non_existent}
    end
  end

  def authenticate_user(%{"email" => email, "password" => password}) do
    with %User{} = user <- get_by(%{email: email}),
      {:ok} <- verify_password(password, user.password_hash),
      do: {:ok, user}
  end

这些参数与具有字符串键的地图匹配。正如我所提到的那样,我这样做是因为我可以直接从控制器传递params并且模式匹配传入的内容(在这种情况下,是各种登录方法)。是否有一种标准的凤凰方式来解决这类问题?

1 个答案:

答案 0 :(得分:0)

以下是使用模式匹配的一种可能解决方案。

它可能不是最美丽的解决方案,但我认为字符串和原子键都不匹配。

  def update_user(%User{} = user, attrs) do
    user
    |> user_changeset(attrs)
    |> Repo.update()
  end

  def user_changeset(user, attrs) do
    case attrs do
      %{"password" => _} ->
        User.password_changeset(user, Map.put(attrs, "password_reset_token", nil))

      %{password: _} ->
        User.password_changeset(user, Map.put(attrs, :password_reset_token, nil))

      %{"password_reset_token" => _} ->
        User.password_reset_changeset(user, attrs)

      %{password_reset_token: _} ->
        User.password_reset_changeset(user, attrs)

      _ ->
        User.changeset(user, attrs)
    end
  end

此外,您可以为所有情况模式匹配函数参数,但我认为在这种情况下更复杂。

另一种选择是首先将所有attrs映射转换为字符串键(反之,动态生成原子通常被认为是个坏主意)。