Elixir - 在特殊情况下不做任何事情

skw*_*eth 5 elixir

caseElixir的一份声明中,如果在case声明中满足特定条件,是否可以不采取任何措施?或者必须总是返回一些东西?

为了说明,这里是我正在研究的凤凰应用程序的片段:

Enum.map(record_params, fn(record_id) ->
    record = Repo.get!(Record, record_id)
    case Repo.update(record) do
        {:ok, struct} ->
            # I DON'T REALLY NEED ANYTHING TO HAPPEN HERE... BUT I HAVE TO HAVE A CLAUSE TO MATCH WHEN THE UPDATE RETURNS {:ok, struct}
            IO.inspect struct
        {:error, changeset} ->
            errors = parse_errors(changeset)
            IO.inspect errors
            json(conn |> put_status(400), %{status: "error", message: "There was a problem updating this record.", errors: errors})
                end
end)
Run Code Online (Sandbox Code Playgroud)

如果record更新了,我需要知道是否有错误,获取有关它的信息,并将其返回给客户端,因此需要case声明...但如果记录已被删除,我真的不需要做任何事情更新成功 - {:ok, struct}.由于这些更新发生在一个内部Enum.map(),如果更新成功,我只希望地图继续循环record_ids.

目前,我刚刚投入IO.inspect struct了成功的条件 - 这是无害的,但并非真的有必要.如果可能的话,我更愿意清理我的代码.{:ok, struct}由于Elixir的模式匹配,我无法删除条件,如果在这种情况下我什么都没有,我得到了错误syntax error before: '->'.

现在我对Elixir(以及一般的函数式编程范例)完全不熟悉,所以如果有更多'Elixirish'方式来处理这种情况,我很乐意听到它.

Ale*_*kin 12

尽管已经有很多答案,但我会发布另一个答案.除了一个回归之外,惯用的Elixir方法将使用Kernel.SpecialForms.with/1:

with {:error, changeset} <- Repo.update(record) do
  # Do whatever you want here
end
Run Code Online (Sandbox Code Playgroud)

do当且仅发生匹配时将执行该块,否则将执行不匹配的RHO值({:ok, _}将直接返回.)

要正确执行您想要的代码,请参阅@ Dogbert的答案.


Dog*_*ert 3

您的代码是错误的,因为您可能会json多次调用同一代码conn,以防出现多个Repo.update错误。在这种情况下,您需要停止处理列表的其余部分。另外,由于您实际上并没有检测到何时出现任何错误,因此您可能json稍后会无条件地再次调用同一conn. conn如果您查看日志,您应该会看到 Phoenix多次写入相同的响应,例如

\n\n
[debug] Processing by MyApp.PageController.index/2\n  Parameters: %{}\n  Pipelines: [:browser]\n[info] Sent 200 in 130\xc2\xb5s\n[info] Sent 200 in 232\xc2\xb5s\n[info] Sent 200 in 498\xc2\xb5s\n[info] Sent 200 in 390\xc2\xb5s\n[info] Sent 200 in 182\xc2\xb5s\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的做法Enum.reduce_while/3

\n\n
errors = Enum.reduce_while(record_params, nil, fn(record_id, nil) ->\n  record = Repo.get!(Record, record_id)\n  case Repo.update(record) do\n    {:ok, struct} ->\n      {:cont, nil}\n    {:error, changeset} ->\n      errors = parse_errors(changeset)\n      {:halt, errors}\n  end\nend)\n\nif errors do\n  json(conn |> put_status(400), %{status: "error", message: "There was a problem updating this record.", errors: errors})\nelse\n  json(conn, "no errors!")\nend\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这真的很酷 - 你是对的,我的设置方式肯定是不正确的,这可能会多次调用“json”。非常感谢,这真的很有帮助。 (2认同)