I have a small pipeline in elixir, it's about changing ecto
model state:
model
|> cast(params, ~w(something), ~w())
|> conditional
|> Repo.update
The problem is that I have conditional
pipe which can be nil sometimes, so in the case it's nil it should do nothing and can works (I presume it will be fn(x) -> x end
)
So, my question is: "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
Not sure if I got your question right, but maybe thats what you are looking for.
Pipes are great for operations that can't fail and all of them always will be carried. In case you want to stop the pipeline, you can't. You would have to write functions like this:
maybe_repo_update(nil), do: nil
maybe_repo_update(data), do: Repo.update(data)
To solve that problem there is a new special form in Elixir 1.2 called with
. It can stop the pipeline at the moment where something doesn't match:
with changeset <- cast(model, params, ~w(something), ~w())
{:ok, changeset} <- conditional_operation(changeset)
{:ok, model} <- Repo.insert(changeset)
This will make sure that if conditional operation returns something else than {:ok, changeset}
it will not try to run the last repo insert. In Elixir 1.3 you can also use else
part.
However for changesets it is more common to use solution suggested by @JustMichael:
def conditional(changeset) do
if something_to_do do
transform(changeset)
else
changeset
end
end
This solution will always run the Repo.update
part.
I'm Elixir newbie, so please don't be too harsh :).
Why not use anonymous functions for this purpose ?
model
|> cast(params, ~w(something), ~w())
|> (fn(n) -> conditional && n |> Repo.update || n end).()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With