elixir - 如何将条件管道添加到管道中?

elixir - how to add conditional pipe into pipeline?

我在 elixir 中有一个小管道,它是关于改变 ecto 模型状态的:

model
|> cast(params, ~w(something), ~w())
|> conditional
|> Repo.update

问题是我有 conditional 管道,有时它可能为 nil,所以在它为 nil 的情况下它应该什么也不做并且可以工作(我假设它将是 fn(x) -> x end

那么,我的问题是:"how can I do that"?

model
|> cast(params, ~w(something), ~w())
|> maybe_do_something(conditional)
|> Repo.update

defp maybe_do_something(changeset, nil), do: changeset

defp maybe_do_something(changeset, func) do
  # Do something with changeset
end

不确定我是否答对了你的问题,但也许这就是你要找的。

管道非常适合不会失败的操作,所有这些操作都将始终进行。如果你想停止管道,你不能。你必须这样写函数:

maybe_repo_update(nil), do: nil
maybe_repo_update(data), do: Repo.update(data)

为了解决这个问题,Elixir 1.2 中有一个新的特殊形式,叫做 with。它可以在不匹配的时候停止管道:

with changeset <- cast(model, params, ~w(something), ~w())
  {:ok, changeset} <- conditional_operation(changeset)
  {:ok, model} <- Repo.insert(changeset)

这将确保如果条件操作 returns 除了 {:ok, changeset} 之外,它不会尝试 运行 最后一个 repo 插入。在 Elixir 1.3 中,您还可以使用 else 部分。

然而,对于变更集,更常见的是使用@JustMichael 建议的解决方案:

def conditional(changeset) do
  if something_to_do do
    transform(changeset)
  else
    changeset
  end
end

此解决方案将始终 运行 Repo.update 部分。

我是 Elixir 新手,所以请不要太苛刻:)。

为什么不为此目的使用匿名函数?

model
|> cast(params, ~w(something), ~w())
|> (fn(n) -> conditional && n |> Repo.update || n end).()