Skip to content

Instantly share code, notes, and snippets.

@blakedietz
Created August 13, 2024 15:45
Show Gist options
  • Save blakedietz/4a0dfac8d84f85e5015a376db1f9eaa2 to your computer and use it in GitHub Desktop.
Save blakedietz/4a0dfac8d84f85e5015a376db1f9eaa2 to your computer and use it in GitHub Desktop.
defmodule App do
@moduledoc """
App keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""
def example() do
App.CustomRepo.transact_with_side_effects(fn ->
with {:ok, new_person} <-
App.Examples.create_person(%{
"first_name" => "Alan",
"last_name" => "Turing",
"age" => 50
}),
{:ok, _} <- App.Examples.update_person(new_person, %{"age" => 52}) do
IO.puts("Made it")
end
end)
end
end
defmodule App.CustomRepo do
def transact_with_side_effects(transaction_function) do
:erlang.put(:scratch_transaction_side_effects, [])
App.Repo.transaction(transaction_function)
|> tap(fn
{:ok, result} ->
:erlang.get(:scratch_transaction_side_effects)
|> Enum.each(fn side_effect_fn ->
side_effect_fn.(result)
end)
_ ->
nil
end)
end
def register_side_effects(side_effect_fns) when is_list(side_effect_fns) do
current_transaction_side_effects = :erlang.get(:scratch_transaction_side_effects)
:erlang.put(
:scratch_transaction_side_effects,
side_effect_fns ++ current_transaction_side_effects
)
end
end
defmodule App.Examples do
@moduledoc """
The Examples context.
"""
import Ecto.Query, warn: false
alias App.Repo
alias App.Examples.Person
# ...
@doc """
Creates a person.
## Examples
iex> create_person(%{field: value})
{:ok, %Person{}}
iex> create_person(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_person(attrs \\ %{}) do
App.CustomRepo.register_side_effects([
fn result ->
IO.inspect(result)
end
])
%Person{}
|> Person.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a person.
## Examples
iex> update_person(person, %{field: new_value})
{:ok, %Person{}}
iex> update_person(person, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_person(%Person{} = person, attrs) do
App.CustomRepo.register_side_effects([
fn result ->
IO.inspect(result)
end
])
person
|> Person.changeset(attrs)
|> Repo.update()
end
# ...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment