EctoJuno is a package that provides parsing, validation and applying sorting parameters for your ecto queries on models. Currently sorting by joint query is not implemented, as well as custom validators for your parameters. Also you need elixir 1.14 to use this package. Hope this package will help someone not just me ). Looking for a feedback, so if you have any thoughts, please share.
Below is a sample usage of library (assuming you have User ecto schema and Repo module):
alias EctoJuno.Query.Sorting
def list_sorted_users_for_admin(params) do
User
|> Sorting.sort_query(User, params)
|> Repo.all()
end
def list_sorted_users_for_manager(params) do
User
|> Sorting.sort_query([:id, :inserted_at], params)
|> Repo.all()
end
2 Likes
Released v0.2.0 version in which added sorting by joint query.
Let’s assume you have User and Post schemas, Repo module. And users has many posts. If you need sort users by post’s titles than your code will look like:
alias EctoJuno.Query.Sorting
def sort_users_by_posts do
params = %{"sort_by" => "title", "sort_direction" => "desc"}
User
|> join(:left, [u], p in assoc(u, :posts), as: :posts)
|> Sorting.sort_query(User, params, :posts)
|> Repo.all()
end
In the next version there’ll be sorting templates: you can define which schema and or binding will be used based on sorting field you passing by
Released custom schema pickup based on provided sort_by field feature.
Example template definition:
defmodule Sample.UserSorting do
use EctoJuno.Query.SortingTemplate
def prepare_sorting_params("post_" <> field) do
{Post, field, :posts}
end
def prepare_sorting_params(nil) do
{User, "inserted_at"}
end
def prepare_sorting_params(field) do
{User, field}
end
end
Example usage:
# Sort by post's title column
User
|> join(:left, [u], p in assoc(u, :posts), as: :posts)
|> UserSorting.sort_query(%{sort_by: "post_title", sort_direction: "desc"})
|> Repo.all()
# Sort by user's age column
User
|> join(:left, [u], p in assoc(u, :posts), as: :posts)
|> UserSorting.sort_query(%{sort_by: "age", sort_direction: "desc"})
|> Repo.all()