defmodule Flagsmith.Schemas.Identity do use TypedEctoSchema import Ecto.Changeset @moduledoc """ Ecto schema representing an object containing a Flagsmith identity with flags and traits. """ @primary_key false typed_embedded_schema do field(:django_id, :integer) field(:identifier, :string) field(:environment_key, :string) embeds_many(:identity_features, Flagsmith.Schemas.Features.FeatureState) embeds_many(:traits, Flagsmith.Schemas.Traits.Trait) end @doc false @spec changeset(map()) :: Ecto.Changeset.t() @spec changeset(__MODULE__.t(), map()) :: Ecto.Changeset.t() def changeset(struct \\ %__MODULE__{}, params) do struct |> cast(params, [:identifier, :environment_key, :django_id]) |> validate_required([:identifier]) |> cast_embed(:traits) |> cast_embed(:identity_features) end @doc false @spec from_id_traits( identifier :: String.t(), Flagsmith.Schemas.Traits.Trait.from_types(), environment_key :: nil | String.t() ) :: __MODULE__.t() def from_id_traits(identifier, traits, environment_key \\ nil), do: %__MODULE__{ identifier: identifier, environment_key: environment_key, traits: Flagsmith.Schemas.Traits.Trait.from(traits) } @doc false @spec from_response(element :: map() | list(map())) :: __MODULE__.t() | any() def from_response(element) when is_map(element) do Map.put(element, "identity_features", Map.get(element, "flags")) |> changeset() |> apply_changes() end def from_response(elements) when is_list(elements) do Enum.map(elements, fn element -> from_response(element) end) end def from_response(element), do: element @doc false @spec set_env_key(__MODULE__.t(), Flagsmith.Schemas.Environment.t() | String.t()) :: __MODULE__.t() def set_env_key(%__MODULE__{} = struct, %Flagsmith.Schemas.Environment{api_key: environment_key}) when is_binary(environment_key), do: set_env_key(struct, environment_key) def set_env_key(%__MODULE__{} = struct, environment_key) when is_binary(environment_key), do: %{struct | environment_key: environment_key} @doc false @spec composite_key(__MODULE__.t()) :: String.t() | non_neg_integer() def composite_key(%__MODULE__{django_id: django_id}) when is_integer(django_id), do: django_id def composite_key(%__MODULE__{identifier: identifier, environment_key: environment_key}) when is_binary(environment_key), do: "#{environment_key}_#{identifier}" @doc false @spec composite_key(__MODULE__.t(), String.t()) :: String.t() def composite_key(%__MODULE__{identifier: identifier}, environment_key) when is_binary(environment_key), do: "#{environment_key}_#{identifier}" end