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

问题描述:

我有以下函数定义,我试图找到一种方法来简化参数,使它们都是统一的。Phoenix:上下文中的模式匹配参数(原子和字符串)

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 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与一个地图,其具有字符串键匹配:

对比度与下文中,这需要直接从一个控制器功能(def create(conn, params))PARAMS。正如我所说,我这样做,因为那样我可以直接从控制器传递params,并且模式匹配传入的内容(在这种情况下是各种登录方法)。是否有标准的凤凰方式来解决这类问题?

+0

一种方法是将所有原子键转换为字符串键,然后仅对字符串进行模式匹配。另一种方法是使用'cond',例如'cond do attrs [“password”] || attrs [:密码] - >#密码存在...'。我宁愿只用字符串键调用函数,因此只需要一个模式匹配(因为你不能改变具有字符串键的'params'的行为)。 – Dogbert

这里是一个可能的解决方案:

它可能不是最漂亮的解决方案,但我不认为两个字符串和原子键永远是匹配的。

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图转换为字符串键(相反,动态生成原子通常被认为是一个坏主意)。