Created
April 2, 2021 17:37
-
-
Save baldwindavid/780449125ac4e9d064662895a0d65703 to your computer and use it in GitHub Desktop.
Build Stubbed Strategy for ExMachina
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Factories.BuildStubbedStrategy do | |
use ExMachina.Strategy, function_name: :build_stubbed | |
alias Ecto.Association.BelongsTo | |
alias Ecto.Association.Has | |
alias Ecto.Association.NotLoaded | |
alias Ecto.UUID | |
def handle_build_stubbed(record, _opts \\ []) do | |
record | |
|> ensure_id() | |
|> ensure_inserted_at() | |
|> ensure_updated_at() | |
|> stub_associations() | |
end | |
defp ensure_id(%{id: nil} = record), do: Map.put(record, :id, UUID.generate()) | |
defp ensure_id(record), do: record | |
defp ensure_inserted_at(%{inserted_at: nil} = record), do: Map.put(record, :inserted_at, now()) | |
defp ensure_inserted_at(record), do: record | |
defp ensure_updated_at(%{updated_at: nil} = record), do: Map.put(record, :updated_at, now()) | |
defp ensure_updated_at(record), do: record | |
defp stub_associations(record) do | |
record.__struct__.__schema__(:associations) | |
|> Enum.map(&record.__struct__.__schema__(:association, &1)) | |
|> Enum.reduce(record, fn assoc_type, record -> | |
assoc_name = assoc_type.field | |
assoc_record = Map.get(record, assoc_name) | |
case assoc_record do | |
%NotLoaded{} -> | |
record | |
_ -> | |
stub_association(assoc_type, assoc_name, assoc_record, record) | |
end | |
end) | |
end | |
defp stub_association(%BelongsTo{owner_key: assoc_fk_name}, assoc_name, parent, record) do | |
parent = handle_build_stubbed(parent) | |
record | |
|> Map.put(assoc_name, parent) | |
|> Map.put(assoc_fk_name, parent.id) | |
end | |
defp stub_association(%Has{cardinality: :one}, assoc_name, child, record) do | |
child = handle_build_stubbed(child) | |
Map.put(record, assoc_name, child) | |
end | |
defp stub_association(%Has{cardinality: :many}, assoc_name, children, record) do | |
children = Enum.map(children, fn child -> handle_build_stubbed(child) end) | |
Map.put(record, assoc_name, children) | |
end | |
defp now, do: DateTime.truncate(Timex.now(), :second) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment