Skip to main content

lib/rulestead/ruleset/rollout.ex

defmodule Rulestead.Ruleset.Rollout do
  @moduledoc false

  use Ecto.Schema

  import Ecto.Changeset

  alias Rulestead.Ruleset.Guardrail

  @primary_key false

  @bucket_by_values [:subject, :account, :tenant, :session]

  embedded_schema do
    field(:bucket_by, Ecto.Enum, values: @bucket_by_values)
    field(:percentage, :integer)
    field(:salt, :string)
    embeds_many(:guardrails, Guardrail, on_replace: :delete)
  end

  @type t :: %__MODULE__{}

  @spec changeset(t(), map()) :: Ecto.Changeset.t()
  def changeset(rollout, attrs) do
    rollout
    |> cast(attrs, [:bucket_by, :percentage, :salt])
    |> update_change(:salt, &normalize_string/1)
    |> cast_embed(:guardrails, with: &Guardrail.changeset/2)
    |> validate_required([:bucket_by, :percentage])
    |> validate_number(:percentage, greater_than_or_equal_to: 0, less_than_or_equal_to: 100)
    |> validate_length(:salt, max: 255)
  end

  @spec bucket_by_values() :: [atom()]
  def bucket_by_values, do: @bucket_by_values

  defp normalize_string(value) when is_binary(value), do: String.trim(value)
  defp normalize_string(value), do: value
end