Elixir,Ecto模式匹配条件与db查询的行为不符合预期 [英] Elixir, Ecto pattern matching conditional with db query not behaving as expected
问题描述
如果该记录不存在,我希望此条件可以创建它,但是它不....返回nil。
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!
推荐答案
根据文档
案例
允许我们将值与许多模式进行比较,直到我们
找到匹配的模式为止:
case
allows us to compare a value against many patterns until we find a matching one:
在另一个模式中单词,第一个匹配的案例将运行,而 case
不会继续进行。
In another word, the first matching case will run and case
will not proceed further.
在您的第一个示例中,第一个因为您不提供任何保护,所以大小写总是匹配的,因此 struct
将绑定到 nil
。第二种方法解决了问题,因为您首先要对特定情况进行模式匹配,然后通过将 case
的求值绑定到 struct来默认为一般情况
。
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
.
还请注意,您可以使用gua rds在您的第一种情况下,请确保 struct
的值是 map
的此处。
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
这篇关于Elixir,Ecto模式匹配条件与db查询的行为不符合预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!