defmodule Funx.Predicate.NotIn do @moduledoc """ Predicate that checks if a value is not a member of a given collection using an `Eq` comparator. Options - `:values` (required) The list of disallowed values. - `:eq` (optional) An equality comparator. Defaults to `Funx.Eq.Protocol`. ## Examples use Funx.Predicate # Check if status is not one of disallowed values pred do check :status, {NotIn, values: [:deleted, :archived]} end # Check if struct type is not in list pred do check :event, {NotIn, values: [DeprecatedEvent, LegacyEvent]} end # With custom Eq comparator pred do check :item, {NotIn, values: blocked_items, eq: Item.Eq} end """ @behaviour Funx.Predicate.Dsl.Behaviour alias Funx.List @impl true def pred(opts) do values = Keyword.fetch!(opts, :values) eq = Keyword.get(opts, :eq, Funx.Eq.Protocol) module_values? = is_list(values) and Enum.all?(values, &is_atom/1) fn value -> case {value, module_values?} do {%{__struct__: mod}, true} -> mod not in values _ -> not List.elem?(values, value, eq) end end end end