2016-04-27 31 views
1

所以我正在寫一個快速異步用戶名驗證檢查,並按照上PhoenixFrameworks網站上的教程中,我能做到這一點,像這樣:怎樣的參數PhoenixFramework(藥劑)結合工作

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

模式匹配不是固有的函數式編程。這只是許多FP語言實現中的一個突出特性。 –

回答

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

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