I have the following function definitions, and I'm trying to find a way to simplify the params so that they're all uniform.
def update_user(%User{} = user, %{password: _} = attrs) do
attrs = Map.put(attrs, :password_reset_token, nil)
update_user(user, attrs, &User.password_changeset/2)
end
def update_user(%User{} = user, %{password_reset_token: _} = attrs), do:
update_user(user, attrs, &User.password_reset_changeset/2)
def update_user(user, attrs), do:
update_user(user, attrs, &User.changeset/2)
def update_user(user, attrs, changeset) do
user
|> changeset.(attrs)
|> Repo.update()
end
A programmer could mess that up I think, by passing in a map with string keys (say for %{"password" => value}) and it'd match with update_user/2. So maybe I should update the params for those functions? Or use a guard on update_user(user, attrs) to not match w/ %{"password" => value}?
Contrast with the following, which takes params straight from a controller function (def create(conn, params)):
def authenticate_user(%{"email" => email, "access_token" => _}) do
case get_by(%{email: email}) do
%User{} = user ->
{:ok, user}
nil ->
{:error, :non_existent}
end
end
def authenticate_user(%{"email" => email, "password" => password}) do
with %User{} = user <- get_by(%{email: email}),
{:ok} <- verify_password(password, user.password_hash),
do: {:ok, user}
end
Those params are matching with a map that has string keys. As I mentioned I'm doing that because then I can pass params straight from the controller and pattern match with what's been passed in (in this case, various login methods). Is there a standard Phoenix way for tackling this kind of problem?
cond, e.g.cond do attrs["password"] || attrs[:password] -> # password exists .... I'd rather just call the function with string keys so only a single pattern match is needed (since you cannot change the behavior ofparamshaving string keys). - Dogbert