所以我正在写一个快速的异步用户名验证检查,并按照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
变量?
答案 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