I just wanted to share with you a small macro that has cleaned up many many lines of code for me.
Basically in my contexts I had this kind of code everywhere
|> Repo.transaction()
|> case do
{:ok, %{goal: goal}} = result ->
PubSub.broadcast_goal_created(user, goal)
result
error ->
error
end
A possible solution would be to add maybe
functions
|> Repo.transaction()
|> maybe_broadcast_goal_created(user)
..
def maybe_broadcast_goal_created({:ok, %{goal: goal}} = result, user) do
PubSub.broadcast_goal_created(user, goal)
result
end
def maybe_broadcast_goal_created(result, user), do: result
Which is not ideal since I’d have to create one pair for each function in context.
Macros to the rescue!
Inspired by how IO.inspect
prints and keeps moving, I created case_continue
, which runs case, ignores it’s result and continues the pipe as if it was never there.
defmodule Timetask.Helpers.Macros do
defmacro case_continue(prev, do: block) do
quote do
case unquote(prev) do
unquote(block ++ [{:->, [], [[{:_, [], nil}], nil]}])
end
unquote(prev)
end
end
end
Now I can write it like this.
|> Repo.transaction()
|> case_continue do
{:ok, %{goal: goal}} -> PubSub.broadcast_goal_created(user, goal)
end
Much nicer huh? What do you think? Do you like the name? I also had in mind case_bridge
or case_skip
.