2017-09-06 71 views
0

我很新的藥劑和鳳凰,但我發現它真的很酷。我來自Rails的背景。鳳凰藥劑 - 重構功能是功能

鑑於這種變更,例如:

def signup(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:email, :password, :password_confirmation, :username]) 
    |> validate_required([:email, :password, :password_confirmation, :username]) 
    |> validate_length(:username, min: 3) 
    |> validate_length(:username, max: 20) 
    |> validate_length(:password, min: 6) 
    |> validate_format(:email, ~r/\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i) 
    |> password_match() 
    |> gen_hash_password() 
    |> set_defaults 
    end 

我有前端代碼不允許用戶上傳的註冊表格無需密碼& password_confirmation,但在執行測試時,我想有一個測試是否檢查傳遞的空值。我周圍有方式是通過在一個非常程序的方式,如果else分支寫着:

defp gen_hash_password(signup) do 
    password = get_change(signup, :password) 
    if password == nil 
    signup 
    else 
    hash = Comeonin.Bcrypt.hashpwsalt(password) 
    signup |> put_change(:password_hash, hash) 
    end 
end 

,否則會導致測試失敗的Bcrypt將給予nil字符串,將無法計算哈希值。 雖然這看起來不太優雅,但我想知道如何才能寫出更好的版本。

我的第一個想法是在驗證通過管道後,通過檢查記錄是否仍然有效,然後我不能像其他語言那樣真的返回。

我的第二個想法是覈實,如果它是有效的,是這樣的:

if valid? do 
    struct 
    |> pipe the remaining changes 
else 
    struct 
end 

,但我似乎還沒有找到查詢變更本身內部結構是否有效的方法是什麼?

感謝

回答

2

changeset傳遞到您的gen_hash_password,你可以簡單地檢查與changeset.valid?變更集的有效性。如果它無效,只需將變更集傳遞回來,因爲它們對於不會保留的記錄散列密碼沒有意義。

這裏是一個示例實現:

defp encrypt_password(changeset) do 
    if changeset.valid? do 
    changeset 
    |> put_change(:password_hash, Comeonin.Bcrypt.hashpwsalt(changeset.changes.password)) 
    else 
    changeset 
    end 
end 
+0

謝謝,這比我有更好的 - 雖然我仍然需要做一個通用函數,然後調用哈希和其餘函數,以防變更是有效的或返回結構,或添加這對所有隨後在變更管道中調用的函數來防止它們也被調用。我的問題大多是迂腐的,但只是想知道我是否錯過了一些非常明顯的東西。 –

+0

IMO沒有必要爲哈希做一個genric函數。只需直接調用Comeonin函數即可。如果變更集有效,則會被散列。如果不是由於任何原因(包括無密碼),它將避免調用哈希函數。 我通常會將與變更集相關的後續功能短路,如上所述。你可以更進一步,將'changeset.valid?'傳遞給這些函數,但這不值得,我不認爲。 – Robert

+0

我不確定我是否理解,我試過''> put_change(:password_hash,Comeonin.Bcrypt.hashpwsalt(params [:password]))'驗證後,它會拋出:'**(ArgumentError)The密碼和鹽應該是字符串,鹽(編碼前)應該是16字節長?謝謝 –

1

這在很大程度上取決於你的原意,但回答的題目中所述的問題:不是if跳舞,在二郎山/花好月圓人做模式匹配。

defp gen_hash_password(signup) do 
    signup 
    |> get_change(:password) 
    |> do_signup() 
end 

defp do_signup(nil), do: signup 
defp do_signup(password) do 
    hash = Comeonin.Bcrypt.hashpwsalt(password) 
    put_change(signup, :password_hash, hash) 
end 
+0

謝謝,這是很好的知道,我一定會在其他地方使用它。 –