2017-09-06 11 views
0

私はElixirとPhoenixにはかなり新しいですが、私はそれが本当にクールだと思っています。私はRailsの背景から来た。私は、ユーザーがパスワード& password_confirmationせずにサインアップフォームを投稿することができませんフロントエンドのコードを持っていますが、実行するテストは、私が持っているしたい場合Phoenix Elixir - 機能するリファクタリング機能

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 

は、例えばこのチェンジを考えます空の値が渡されるかどうかを調べるテスト。私はそれのまわりで得た方法は、他の支店であれば非常に手続き方法のANに書き込むことによってました:bcryptのはnil文字列が与えられますし、ハッシュを計算することができなくなりますよう

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 

そうでない場合、テストは失敗します。 これは非常にエレガントではないようですが、私はどのようにしてより良いバージョンを書くことができるのだろうと思っていました。

私の最初の考えは、バリデーションがパイプされた後、その時点でレコードが有効かどうかをチェックすることで早期復帰を行うことでしたが、他の言語と同じように早く戻ることはできません。それが有効だった場合

私の第二の考えを確認した、のようなもの:

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

しかし、私はチェンジセット自体の内部構造体の妥当性を照会する方法を見つけるように見えるではないのですか?

おかげchangesetがあなたのgen_hash_passwordに渡され

答えて

2

、あなたは単に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ハッシングのジェネリック関数を作成する必要はありません。 'Comeonin'関数を直接呼び出すだけです。チェンジセットが有効な場合は、ハッシュされます。何らかの理由で(nilパスワードを含めて)そうでなければ、ハッシュ関数の呼び出しを避けます。 私は通常、上記のような後続のチェンジセット関連の機能を短絡させます。あなたはそれをさらに進め、 'changeset.valid? 'をこれらの関数に渡すことができますが、それは私が思うに値するものではありません。 – Robert

+0

私は理解していませんが、検証の後に '|> put_change(:password_hash、Comeonin.Bcrypt.hashpwsalt(params [:password]))')を実行しようとしましたが、それはスローされます: '**(ArgumentError)パスワードと塩は文字列でなければならず、塩(コード化前)は16バイト長でなければならない 'おかげで –

1

が、タイトルに記載された質問に答える:

は、ここでサンプル実装ですアーラン/エリクサーのいずれかではなく、if踊りは、パターンマッチングを行います。

+0

ありがとう、これは知っていいと私は確かに他の場所でそれを使用します。 –

関連する問題