First off, I have this “working” with happy_path
(It seems to execute properly, but it’s difficult to exercise the error paths). I am creating this topic for a couple main reasons:
- Is there a “better” way?
- Why isn’t my
with
statement compiling? - Is there a way with
with
statements to have multi-line clauses. - Are nested
with
statements allowed/possible?
So I’ll come back to these questions after the code:
Pyramid of doom with branching case statement in the middle
def start_or_resume_session(session_id) when is_bitstring(session_id) do
case IbGib.Expression.Supervisor.start_expression({"session", "gib"}) do
{:ok, root_session} ->
case get_session_ib(session_id) do
{:ok, session_ib} ->
case get_latest_session_ib_gib(session_id, root_session) do
# I want to do stuff if it's nil
{:ok, nil} ->
case (root_session |> instance(session_ib)) do
{:ok, {_, session}} ->
case session |> get_info do
{:ok, session_info} ->
case get_ib_gib(session_info) do
{:ok, session_ib_gib} -> {:ok, session_ib_gib}
{:error, reason} -> {:error, reason}
end
{:error, reason} -> {:error, reason}
end
{:error, reason} -> {:error, reason}
end
# Return it if not nil
{:ok, existing_session_ib_gib} -> {:ok, existing_session_ib_gib}
{:error, reason} -> {:error, reason}
end
{:error, reason} -> {:error, reason}
end
{:error, reason} -> {:error, reason}
end
end
Attempt with nesting with
(doesn’t compile)
def start_or_resume_session(session_id) when is_bitstring(session_id) do
with {:ok, root_session} <- IbGib.Expression.Supervisor.start_expression({"session", "gib"}),
{:ok, session_ib} <- get_session_ib(session_id),
{:ok, session_ib_gib} <-
case get_latest_session_ib_gib(session_id, root_session) do
{:ok, nil} ->
with {:ok, {_, session}} <- root_session |> instance(session_ib),
{:ok, session_info} <- session |> get_info,
{:ok, session_ib_gib} <- get_ib_gib(session_info) do
{:ok, session_ib_gib}
else
{:error, reason} -> {:error, reason}
end
{:ok, existing_session_ib_gib} -> {:ok, existing_session_ib_gib}
{:error, reason} -> {:error, reason}
end,
do: {:ok, session_ib_gib}
end
end
Attempt with nesting happy_path
(works, I think)
def start_or_resume_session(session_id) when is_bitstring(session_id) do
happy_path do
{:ok, root_session} = IbGib.Expression.Supervisor.start_expression({"session", "gib"})
{:ok, session_ib} = get_session_ib(session_id)
{:ok, existing_session_ib_gib} = get_latest_session_ib_gib(session_id, root_session)
{:ok, session_ib_gib} =
if (existing_session_ib_gib == nil) do
Logger.debug "nil case...are we still on happy path?"
# it's nil, so create a new one and return that
# Are we still on the happy_path? No. So nest another path?
happy_path do
{:ok, {_, session}} = root_session |> instance(session_ib)
{:ok, session_info} = session |> get_info
{:ok, session_ib_gib} = get_ib_gib(session_info)
{:ok, session_ib_gib}
end
else
{:ok, existing_session_ib_gib}
end
{:ok, session_ib_gib}
end
end
Questions
Is there a “better” way?
Overall, could/should I refactor something out? I’m not a huge fan of do_x_or_y
functions, but this seems pretty straight-forward to me, and the long-ish name is more of being precise.
Or, is there a more concise/appropriate way of nesting happy_path
statements?
Why isn’t my with
statement compiling?
The error changes, depending on which permutation of , do:
, or do end
block in the with
statement I use. It’s either there is an unexpected end
later on in the file, or that there is an illegal character before a comma (,
) on the with block. I think it’s balking on the case statement line. Are case statements, or rather full do..end
blocks not allowed with with
clauses?
Is there a way with with
statements to have multi-line clauses.
This is probably related to the previous question.
Everything I’ve seen/read on with
has a single line clause, with each line ending with a comma before the do
block. Is there a way to have a multi-line clause?
Are nested with
statements allowed/possible?
I can’t seem to figure out how to nest with
statements, and I just think that I should. I’m still a little fuzzy on some of the , do:
vs do...end
blocks thing (I didn’t come from a Rails background).