2017-09-06 68 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

谢谢,这是很好的知道,我一定会在其他地方使用它。 –