View Source ExToolkit.Ecto (ExToolkit v0.7.0)
A utility module for handling Ecto queries, with functions to perform common tasks like applying a range filter, and executing a series of query operations in a pipeline. This module includes Ecto changeset validation functions as well.
Summary
Functions
Applies a series of operations to an Ecto query.
Applies pagination to an Ecto query. It calculates the correct offset based on the page number and limits the number of results returned by the query to the specified page size.
Filters a query to only include rows where the specified column's value is within a provided range.
Validates the structure of a URL field in an Ecto changeset. It does not make it required field.
Functions
@spec apply_options(Ecto.Queryable.t(), Keyword.t()) :: Ecto.Queryable.t()
Applies a series of operations to an Ecto query.
Parameters
query
: The Ecto query to which operations should be applied.opts
: A list of operations to apply. Each operation is a tuple where the first element is the operation name and the second element is the value to use for that operation.
The following operations are supported:
{:where, filters}
: Adds awhere
clause to the query.{:select, fields}
: Adds aselect
clause to the query.{:order_by, criteria}
: Adds anorder_by
clause to the query.{:limit, criteria}
: Adds alimit
clause to the query.{:preload, preload}
: Adds apreload
clause to the query.
Invalid options are ignored from query result.
Examples
iex> query = from(u in "users")
iex> apply_options(query, where: [age: 18], select: [:id, :email])
#Ecto.Query<from u0 in "users", where: u0.age == ^18, select: map(u0, [:id, :email])>
iex> query = from(u in "users")
iex> filters = [
...> {:where, [age: 18]},
...> {:order_by, [desc: :age]},
...> {:select, [:id, :email]},
...> {:limit, 10},
...> {:preload, :posts},
...>]
iex> apply_options(query, filters)
#Ecto.Query<from u0 in "users", where: u0.age == ^18, order_by: [desc: u0.age], limit: ^10, select: map(u0, [:id, :email]), preload: [:posts]>
@spec apply_pagination( Ecto.Queryable.t(), binary() | pos_integer(), binary() | pos_integer() ) :: Ecto.Queryable.t()
Applies pagination to an Ecto query. It calculates the correct offset based on the page number and limits the number of results returned by the query to the specified page size.
Parameters
query
- An Ecto.Query or any data structure implementing theEcto.Queryable
protocol.page
- The page number for which data is requested. Can be a positive integer or a string representing an integer.page_size
- The number of items to be included on each page. Can be a positive integer or a string representing an integer.
Returns
- An
Ecto.Queryable.t()
with pagination applied.
This function supports page and page_size values passed as integers or strings. If strings are provided, they are converted to integers. If the conversion is not possible, an error will occur.
Examples
iex> query = from(u in "users", select: u.id)
iex> apply_pagination(query, 1, 20)
#Ecto.Query<from u0 in "users", limit: ^20, offset: ^0, select: u0.id>
iex> query = from(u in "users", select: u.id)
iex> apply_pagination(query, "2", 20)
#Ecto.Query<from u0 in "users", limit: ^20, offset: ^20, select: u0.id>
iex> query = from(u in "users", select: u.id)
iex> apply_pagination(query, 4, 15)
#Ecto.Query<from u0 in "users", limit: ^15, offset: ^45, select: u0.id>
Filters a query to only include rows where the specified column's value is within a provided range.
Parameters
query
: The Ecto query to filter.column
: The column on which to apply the range filter.min..max
: The range of values to filter on.
Examples
iex> query = from(u in "users", select: u.age)
iex> in_range(query, :age, 18..30)
#Ecto.Query<from u0 in "users", where: u0.age >= ^18 and u0.age <= ^30, select: u0.age>
Validates the structure of a URL field in an Ecto changeset. It does not make it required field.
If the field
in the changeset
is a URL, this function ensures that it has a scheme (defaulting to "https://" if
none is present), and then checks the URL's structure against a regular expression.
If the URL's structure is invalid, the error_message
is attached to the field
in the changeset
's errors.
Parameters
changeset
: The Ecto changeset containing the URL to validate.field
: The key (atom) for the field in the changeset containing the URL.error_message
: The error message to attach to thefield
in thechangeset
if the URL is invalid.
Examples
iex> types = %{url: :string}
iex> params = %{url: "https://www.example.com/"}
iex> Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))
...> |> validate_url(:url, "is not a valid url")
#Ecto.Changeset<action: nil, changes: %{url: "https://www.example.com/"}, errors: [], data: %{}, valid?: true>
iex> types = %{url: :string}
iex> params = %{url: "www.example.com/"}
iex> Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))
...> |> validate_url(:url, "is not a valid url")
#Ecto.Changeset<action: nil, changes: %{url: "https://www.example.com/"}, errors: [], data: %{}, valid?: true>
iex> types = %{url: :string}
iex> params = %{url: nil}
iex> Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))
...> |> validate_url(:url, "is not a valid url")
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: %{}, valid?: true>
iex> types = %{url: :string}
iex> params = %{url: "some@invalid_url"}
iex> Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))
...> |> validate_url(:url, "is not a valid url")
#Ecto.Changeset<action: nil, changes: %{url: "https://some@invalid_url"}, errors: [url: {"is not a valid url", [validation: :format]}], data: %{}, valid?: false>
iex> types = %{url: :string}
iex> params = %{url: "Just some random text"}
iex> Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))
...> |> validate_url(:url, "is not a valid url")
#Ecto.Changeset<action: nil, changes: %{url: "https://Just some random text"}, errors: [url: {"is not a valid url", [validation: :format]}], data: %{}, valid?: false>