egze
ContextKit - automatic CRUD operations in your context and more
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:
Most Liked
egze
It still calls the User.changeset function, so one way would be to not cast :is_admin in this changeset.
For the use-case when you do want to update the :is_admin field, you would need to create your own update_user_admin function.
This is how update_#{resource} function is generated context_kit/lib/context_kit/crud/scoped.ex at main · egze/context_kit · GitHub
FedericoAlcantara
egze
Released version 0.3.0
The main feature is the support of Phoenix 1.8 scopes.
Use the new ContextKit.CRUD.Scoped in your context.
defmodule MyApp.Blog do
use ContextKit.CRUD.Scoped,
repo: MyApp.Repo,
schema: MyApp.Blog.Comment,
queries: MyApp.Blog.CommentQueries,
pubsub: MyApp.PubSub, # For realtime notifications via PubSub
scope: Application.compile_env(:my_app, :scopes)[:user] # To gain support for Phoenix 1.8 scopes.
end
Now, besides all the functions from before, you will get all functions with the scope as first argument.
# List all comments
MyApp.Blog.list_comments()
# List all comments belonging to current user
MyApp.Blog.list_comments(socket.assigns.current_scope)
egze
v0.5.0 of ContextKit has just been released.
I noticed that when you list resources, it always selects all schema fields, and there is no way to override it. Now there is.
Example:
MyApp.Comments.list_comments(select: [:id, :text])
This will select only the id and text fields from the database.








