问题
If the record does not exist, I would expect this conditional to create it, but it does not.... nil is returned.
case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
struct ->
struct
nil ->
params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
Repo.insert!(User.changeset(User.__struct__, params))
end
# returns nil.... huwutt???
However, if I change the ordering of the condition, it works. What am I missing here?
case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
nil ->
params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
Repo.insert!(User.changeset(User.__struct__, params))
struct ->
struct
end
# returns a set of 24" pythons, brother.... huzah!
回答1:
According to the documentation
case
allows us to compare a value against many patterns until we find a matching one:
In another word, the first matching case will run and case
will not proceed further.
In your first example, the first case will always be matched since you are not providing any guards, and as such, struct
will bind to nil
. Your second approach solves the problem because you're pattern matching a specific case first, and then defaulting to a general case by binding the evaluation of case
to struct
.
Also note that you can use guards in your first case to make sure that the value of struct
is a map
as outlined here.
case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
struct when is_map(struct) ->
struct
nil ->
params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
Repo.insert!(User.changeset(User.__struct__, params))
end
来源:https://stackoverflow.com/questions/42776078/elixir-ecto-pattern-matching-conditional-with-db-query-not-behaving-as-expected