Elixir,Ecto模式匹配条件与db查询不符合预期

时间:2017-03-14 00:57:13

标签: pattern-matching conditional elixir ecto

如果记录不存在,我希望这个条件创建它,但它不会......返回nil。

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???

但是,如果我改变条件的顺序,它就有效。我在这里缺少什么?

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 个答案:

答案 0 :(得分:2)

根据documentation

  

case允许我们将值与多种模式进行比较,直到我们为止   找到匹配的:

换句话说,第一个匹配的案例将会运行,case将无法继续进行。

在您的第一个示例中,第一个案例将始终匹配,因为您没有提供任何警卫,因此struct将绑定到nil。您的第二种方法可以解决问题,因为您首先对特定案例进行模式匹配,然后通过将case的评估与struct绑定来默认为一般情况。

另请注意,您可以在第一种情况下使用警卫,以确保struct的值为map,如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