ContextKit is a modular toolkit for building robust Phoenix/Ecto contexts with standardized CRUD operations. It helps reduce boilerplate code while providing powerful querying capabilities and built-in pagination support.
Features
Automatic CRUD operation generation
Dynamic query building with extensive filtering options
Built-in pagination support
Flexible and extensible design
Custom query options for complex filtering
Description
I always end up customising the generated context functions via mix phx.gen...
. Typically I want to query records via the list_{resource}
function, paginate records and more. With ContextKit I generate all of that.
Examples
Letβs say, we have a schema MyApp.Accounts.User
. To get the auto-generated functions, you would need to add a small snippet to your context module:
defmodule MyApp.Accounts do
use ContextKit.CRUD,
repo: MyApp.Repo,
schema: MyApp.Accounts.User,
queries: __MODULE__
end
This generates some functions in your module, and you can do things like:
# List all users
Accounts.list_users()
# List with filters and pagination
{users, pagination} = Accounts.list_users(
status: "active",
paginate: [page: 1, per_page: 20]
)
# Get single user
user = Accounts.get_user(123)
user = Accounts.get_user!(123) # Raises if not found
# Get one user by criteria
user = Accounts.one_user(email: "user@example.com")
# Create a new user
MyApp.Accounts.create_user(%{email: "new@example.com"})
# Update a user
MyApp.Accounts.update_user(user, %{email: "updated@example.com"})
# Get a changeset for updates
MyApp.Accounts.change_user(user, %{email: "changed@example.com"})
# Delete user
Accounts.delete_user(user)
Accounts.delete_user(email: "user@example.com")
All the fields in the schema can be queried on automatically. There are many operators for advanced queries.
Accounts.list_users(
filters: [
%{field: :email, op: :ilike, value: "@gmail.com"},
%{field: :status, op: :in, value: ["active", "pending"]},
%{field: :name, op: :like_or, value: ["john", "jane"]}
]
)
Additionally you can define any custom query:
defmodule MyApp.Accounts do
def apply_query_option({:with_active_posts, true}, query) do
query
|> join(:inner, [u], p in assoc(u, :posts))
|> where([_, p], p.status == "active")
end
end
and then you can do: MyApp.Accounts.list_users(with_active_posts: true)
You can also define query functions in a different module. Then just pass it instead of queries: __MODULE__
.
Links
- Hex.pm: https://hex.pm/packages/context_kit
- Hexdocs: https://hexdocs.pm/context_kit/ContextKit.html
- Github: