Cinder.Filter.Helpers (Cinder v0.3.0)

View Source

Helper functions for building and validating custom filters.

This module provides common patterns and utilities that custom filter developers can use to simplify their implementations.

Usage

defmodule MyApp.Filters.CustomFilter do
  use Cinder.Filter
  import Cinder.Filter.Helpers

  @impl true
  def process(raw_value, column) do
    with {:ok, trimmed} <- validate_string_input(raw_value),
         {:ok, parsed} <- parse_custom_value(trimmed) do
      build_filter(:my_filter, parsed, :equals)
    else
      _ -> nil
    end
  end
end

Summary

Functions

Builds a relationship-aware Ash query filter.

Debug helper for filter development.

Extracts filter options with type safety.

Common empty value check for most filter types.

Validates and parses comma-separated values.

Validates date input in ISO 8601 format.

Validates that a module properly implements the Cinder.Filter behaviour.

Validates a filter structure has required fields.

Validates float input with optional min/max bounds.

Validates hex color input.

Validates integer input with optional min/max bounds.

Validates operator is in allowed list.

Validates and trims string input, returning error for empty strings.

Functions

build_ash_filter(query, field, value, operator)

Builds a relationship-aware Ash query filter.

Handles both direct fields and relationship fields using dot notation.

Examples

build_ash_filter(query, "name", "John", :equals)
build_ash_filter(query, "user.name", "John", :equals)

build_filter(type, value, operator, extra_fields \\ [])

Builds a standard filter map.

Examples

iex> build_filter(:my_filter, "value", :equals)
%{type: :my_filter, value: "value", operator: :equals}

iex> build_filter(:slider, 50, :less_than_or_equal, case_sensitive: false)
%{type: :slider, value: 50, operator: :less_than_or_equal, case_sensitive: false}

debug_filter(filter_name, message, data \\ %{})

Debug helper for filter development.

Logs filter processing information when debug is enabled.

Examples

debug_filter("MyFilter", "processing input", %{input: "test"})

extract_option(options, key, default)

Extracts filter options with type safety.

Examples

iex> extract_option([min: 0, max: 100], :min, 50)
0

iex> extract_option([], :min, 50)
50

iex> extract_option(%{min: 0, max: 100}, :min, 50)
0

is_empty_value?(value)

Common empty value check for most filter types.

Examples

iex> is_empty_value?(nil)
true

iex> is_empty_value?("")
true

iex> is_empty_value?([])
true

iex> is_empty_value?(%{value: nil})
true

iex> is_empty_value?("test")
false

validate_csv_input(input, opts \\ [])

Validates and parses comma-separated values.

Examples

iex> validate_csv_input("a,b,c")
{:ok, ["a", "b", "c"]}

iex> validate_csv_input("a, b , c ", trim: true)
{:ok, ["a", "b", "c"]}

iex> validate_csv_input("", min_length: 1)
{:error, :empty}

validate_date_input(value)

Validates date input in ISO 8601 format.

Examples

iex> validate_date_input("2023-12-25")
{:ok, ~D[2023-12-25]}

iex> validate_date_input("invalid-date")
{:error, :invalid}

validate_filter_implementation(module)

Validates that a module properly implements the Cinder.Filter behaviour.

Examples

iex> validate_filter_implementation(MyApp.Filters.ValidFilter)
{:ok, "Filter implementation is valid"}

iex> validate_filter_implementation(InvalidModule)
{:error, ["Missing callback: render/4", "Missing callback: process/2"]}

validate_filter_structure(filter)

Validates a filter structure has required fields.

Examples

iex> validate_filter_structure(%{type: :text, value: "test", operator: :equals})
{:ok, %{type: :text, value: "test", operator: :equals}}

iex> validate_filter_structure(%{type: :text, value: "test"})
{:error, :missing_operator}

validate_float_input(input, opts \\ [])

Validates float input with optional min/max bounds.

Examples

iex> validate_float_input("42.5")
{:ok, 42.5}

iex> validate_float_input("42.5", min: 0.0, max: 100.0)
{:ok, 42.5}

iex> validate_float_input("150.0", max: 100.0)
{:error, :out_of_bounds}

iex> validate_float_input("abc")
{:error, :invalid}

validate_hex_color_input(value)

Validates hex color input.

Examples

iex> validate_hex_color_input("#FF0000")
{:ok, "#ff0000"}

iex> validate_hex_color_input("#fff")
{:error, :invalid}

iex> validate_hex_color_input("red")
{:error, :invalid}

validate_integer_input(input, opts \\ [])

Validates integer input with optional min/max bounds.

Examples

iex> validate_integer_input("42")
{:ok, 42}

iex> validate_integer_input("42", min: 0, max: 100)
{:ok, 42}

iex> validate_integer_input("150", max: 100)
{:error, :out_of_bounds}

iex> validate_integer_input("abc")
{:error, :invalid}

validate_operator(operator, allowed_operators)

Validates operator is in allowed list.

Examples

iex> validate_operator(:equals, [:equals, :contains])
{:ok, :equals}

iex> validate_operator(:invalid, [:equals, :contains])
{:error, :invalid_operator}

validate_string_input(value)

Validates and trims string input, returning error for empty strings.

Examples

iex> validate_string_input("  hello  ")
{:ok, "hello"}

iex> validate_string_input("")
{:error, :empty}

iex> validate_string_input(nil)
{:error, :invalid}