FatEcto.SharedHelper (FatEcto v1.4.0)
View SourceProvides utility functions for FatEcto, including handling pagination limits, skip values, dynamic binding, and preloading associations.
Summary
Functions
Checks if a value is an alias tuple: {schema_field_atom, operators}.
Builds a map of API name => schema field atom from a filterable config.
Builds a map of field_name => binding for join filters.
Builds a map of API name => schema field atom from a sortable config.
Extracts field names from join filters as strings for overrideable list.
Converts a filterable option list to a map format if it's a keyword list.
Flattens a filterable config into a map of field => operators.
Like flatten_filterable_to_map/1 but preserves operators for join fields.
Retrieves the primary keys for a given query.
Checks if a module implements the given behaviour by inspecting its __info__/1 metadata.
Checks if a filterable entry is a join filter (nested keyword list).
Converts a keyword list to a map with string keys.
Converts a keyword list to a map with string keys and normalizes operator values to uppercase.
Parses an integer from a string or returns the integer if already an integer.
Separates filterable into direct filters and join filters.
Converts a string to an atom.
Converts a string to an existing atom.
Converts various date/datetime inputs to an Elixir Date struct.
Converts various date/datetime inputs to an Elixir Date struct.
Functions
Checks if a value is an alias tuple: {schema_field_atom, operators}.
Alias tuples allow using a different API name than the actual schema field.
Examples
iex> FatEcto.SharedHelper.alias_entry?({:name, ["$ILIKE"]})
true
iex> FatEcto.SharedHelper.alias_entry?({:name, "*"})
true
iex> FatEcto.SharedHelper.alias_entry?(["$ILIKE"])
false
iex> FatEcto.SharedHelper.alias_entry?("*")
false
Builds a map of API name => schema field atom from a filterable config.
Only includes entries that use the alias tuple syntax {:schema_field, operators}.
Non-aliased fields are not included (they use the API name as-is).
Examples
iex> FatEcto.SharedHelper.build_field_aliases([
...> title: ["$ILIKE"],
...> author_name: {:name, ["$ILIKE"]},
...> classifications: [
...> grade_id: ["$EQUAL"],
...> subject_name: {:name, ["$EQUAL"]}
...> ]
...> ])
%{"author_name" => :name, "subject_name" => :name}
iex> FatEcto.SharedHelper.build_field_aliases([title: ["$ILIKE"], rating: ["$GT"]])
%{}
Builds a map of field_name => binding for join filters.
This map is used by Builder to determine which fields should use JoinOperatorApplier instead of the standard OperatorApplier.
Examples
iex> FatEcto.SharedHelper.build_join_filters_map([classifications: [subject_id: ["$EQUAL"], grade_id: ["$EQUAL"]]])
%{"subject_id" => :classifications, "grade_id" => :classifications}
iex> FatEcto.SharedHelper.build_join_filters_map([])
%{}
Builds a map of API name => schema field atom from a sortable config.
Only includes entries that use the alias tuple syntax {:schema_field, directions}.
Examples
iex> FatEcto.SharedHelper.build_sort_aliases([
...> inserted_at: "*",
...> author_name: {:name, "*"}
...> ])
%{"author_name" => :name}
iex> FatEcto.SharedHelper.build_sort_aliases([inserted_at: "*", views_count: "*"])
%{}
Extracts field names from join filters as strings for overrideable list.
Examples
iex> FatEcto.SharedHelper.extract_join_filter_fields([classifications: [subject_id: ["$EQUAL"], grade_id: ["$EQUAL"]]])
["subject_id", "grade_id"]
iex> FatEcto.SharedHelper.extract_join_filter_fields([])
[]
@spec filterable_opt_to_map(maybe_improper_list() | any()) :: maybe_improper_list() | map()
Converts a filterable option list to a map format if it's a keyword list.
This function checks if the input is a keyword list and converts it to a map. If the input is not a list or not a keyword list, it returns the input unchanged. Alias tuples are unwrapped to extract the operators.
Parameters
list- Input that may be a keyword list, regular list, or other type
Examples
iex> FatEcto.SharedHelper.filterable_opt_to_map([name: ["$LIKE"], age: ["$GT"]])
%{"name" => ["$LIKE"], "age" => ["$GT"]}
iex> FatEcto.SharedHelper.filterable_opt_to_map(%{"name" => ["$LIKE"]})
%{"name" => ["$LIKE"]}
iex> FatEcto.SharedHelper.filterable_opt_to_map([author_name: {:name, "*"}])
%{"author_name" => "*"}
Flattens a filterable config into a map of field => operators.
Direct filters: {field, [operators]} -> {"field" => [uppercase_ops]} Join filters: {assoc, [nested]} -> each nested field gets "*" wildcard
This is the main function to convert filterable option to a field map.
Examples
iex> FatEcto.SharedHelper.flatten_filterable_to_map([title: ["$ilike"], classifications: [subject_id: ["$EQUAL"]]])
%{"title" => ["$ILIKE"], "subject_id" => "*"}
iex> FatEcto.SharedHelper.flatten_filterable_to_map([name: ["$equal"], age: ["$gt"]])
%{"name" => ["$EQUAL"], "age" => ["$GT"]}
Like flatten_filterable_to_map/1 but preserves operators for join fields.
Examples
iex> FatEcto.SharedHelper.flatten_sortable_to_map([id: "*", fat_rooms: [floor: "*", is_active: ["$ASC", "$DESC"]]])
%{"id" => "*", "floor" => "*", "is_active" => ["$ASC", "$DESC"]}
@spec get_primary_keys(Ecto.Query.t()) :: [atom()] | nil
Retrieves the primary keys for a given query.
Parameters
query: The Ecto query.
Examples
iex> FatEcto.SharedHelper.get_primary_keys(from(u in User))
[:id]
Checks if a module implements the given behaviour by inspecting its __info__/1 metadata.
Parameters
module: The module to check.behaviour: The behaviour to validate against.
Examples
iex> implements_behaviour?(MyApp.Repo, Ecto.Repo)
true
iex> implements_behaviour?(NotARepo, Ecto.Repo)
false
Checks if a filterable entry is a join filter (nested keyword list).
A join filter is detected when the value is a keyword list (nested fields) rather than a list of operator strings.
Examples
iex> FatEcto.SharedHelper.join_filter?({:title, ["$ILIKE"]})
false
iex> FatEcto.SharedHelper.join_filter?({:classifications, [subject_id: ["$EQUAL"]]})
true
iex> FatEcto.SharedHelper.join_filter?({:name, "*"})
false
Converts a keyword list to a map with string keys.
If the input is already a map or not a keyword list, returns it unchanged.
Parameters
list- A keyword list or map to convert
Examples
iex> FatEcto.SharedHelper.keyword_list_to_map([name: "John", age: 25])
%{"name" => "John", "age" => 25}
iex> FatEcto.SharedHelper.keyword_list_to_map(%{"name" => "John"})
%{"name" => "John"}
Converts a keyword list to a map with string keys and normalizes operator values to uppercase.
This function is specifically designed for processing filterable options where operator values need to be normalized to uppercase format.
Parameters
list- A keyword list or map to convert
Examples
iex> FatEcto.SharedHelper.keyword_list_to_map_with_uppercase_operators([name: ["like"], age: ["gt"]])
%{"name" => ["LIKE"], "age" => ["GT"]}
Parses an integer from a string or returns the integer if already an integer.
Returns the parsed integer on success or nil on failure.
Separates filterable into direct filters and join filters.
Direct filters have a list of operator strings as values. Join filters have a nested keyword list as values.
Examples
iex> FatEcto.SharedHelper.separate_filterables([title: ["$ILIKE"], classifications: [subject_id: ["$EQUAL"]]])
{[title: ["$ILIKE"]], [classifications: [subject_id: ["$EQUAL"]]]}
iex> FatEcto.SharedHelper.separate_filterables([name: ["$EQUAL"], age: ["$GT"]])
{[name: ["$EQUAL"], age: ["$GT"]], []}
Converts a string to an atom.
Parameters
str: The string to convert.
Examples
iex> FatEcto.SharedHelper.string_to_atom("example")
:example
Converts a string to an existing atom.
Parameters
str: The string to convert.
Examples
iex> FatEcto.SharedHelper.string_to_existing_atom("example")
:example
@spec to_date(String.t() | Date.t() | DateTime.t()) :: {:ok, Date.t()} | {:error, atom()}
Converts various date/datetime inputs to an Elixir Date struct.
Accepts:
- String date (e.g., "2023-12-25")
- String datetime (e.g., "2023-12-25T10:30:00Z", "2023-12-25 10:30:00")
- Elixir Date struct
- Elixir DateTime struct
Returns {:ok, date} on success or {:error, reason} on failure.
Examples
iex> FatEcto.SharedHelper.to_date("2023-12-25")
{:ok, ~D[2023-12-25]}
iex> FatEcto.SharedHelper.to_date("2023-12-25T10:30:00Z")
{:ok, ~D[2023-12-25]}
iex> FatEcto.SharedHelper.to_date(~D[2023-12-25])
{:ok, ~D[2023-12-25]}
iex> FatEcto.SharedHelper.to_date(~U[2023-12-25 10:30:00Z])
{:ok, ~D[2023-12-25]}
@spec to_date!(String.t() | Date.t() | DateTime.t()) :: Date.t()
Converts various date/datetime inputs to an Elixir Date struct.
Similar to to_date/1 but raises an exception on failure.
Examples
iex> FatEcto.SharedHelper.to_date!("2023-12-25")
~D[2023-12-25]
iex> FatEcto.SharedHelper.to_date!(~U[2023-12-25 10:30:00Z])
~D[2023-12-25]