PhoenixFramework(Elixir)中的参数绑定如何工作

时间:2016-04-27 02:56:54

标签: elixir phoenix-framework

所以我正在写一个快速的异步用户名验证检查,并按照PhoenixFrameworks网站上的教程,我可以这样做:

def validateUsername(conn, %{"username" => user}) do
    IO.inspect(conn)
    query = from u in User,
      where: u.username == ^user,
      select: [u.username]

    case Repo.all(query) do
      [[username]] -> 
        conn
        |> json(%{ success: false, error: "Username has been taken" })
      [] ->
        conn
        |> json(%{ success: true })
      nil -> 
        conn
        |> json(%{ success: true })
      _ ->
        conn
        |> json(%{ success: false, error: "Internal Server Error"})
    end

但这对我来说没有多大意义,因为我从未处理过函数式编程语言,而且我知道elixir中与=的数据绑定工作方式不同。但在我的脑海里,我觉得它应该像以下一样逆转:

def validateUsername(conn, %{user => "username"})

或类似的东西所以我的主要问题是

%{"username" => user})如何使用相关信息填充user变量?

2 个答案:

答案 0 :(得分:2)

  

%{"username" => user})如何使用相关信息填充用户变量?

这就是Elixir中模式匹配的工作方式。键应该与地图中的键匹配,并且值应该是与地图中该键的值匹配的模式。如果它是一个普通变量,它只会被分配值。

另外,假设您的数据库对users表中的用户名有唯一约束,我会重写原始代码以使用Repo.get_by/2

def validateUsername(conn, %{"username" = user}) do
  case Repo.get_by(User, username: user) do
    nil -> 
      conn
      |> json(%{ success: true })
    user -> 
      conn
      |> json(%{ success: false, error: "Username has been taken" })
  end
end

def validateUsername(conn, %{"username" = user}) do
  if Repo.get_by(User, username: user) do
    conn
    |> json(%{ success: false, error: "Username has been taken" })
  else
    conn
    |> json(%{ success: true })
  end
end

答案 1 :(得分:2)

如果右侧具有“正确的形状”,模式匹配可以被认为是在表达式左侧分配所有变量的东西。

{a, b} = {1, 2} # now a = 1, b = 2
%{"username" => user} = %{"username" => "Tomasz", "password" => "secret"} # now user = "Tomasz"
[a, b, c] = [:a, "b", 1] # a = :a, b = :b, c = 1
{a, b} = {1, 2, 3} # error

它也适用于嵌套数据!

{[a, b, 3], {c, 5}} = {[1, 2, 3], {4, 5}}

“编程凤凰”中有一个非常全面的模式匹配指南,其中还包括pin operator