egze

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

  • :rocket: Automatic CRUD operation generation
  • :magnifying_glass_tilted_left: Dynamic query building with extensive filtering options
  • :page_facing_up: Built-in pagination support
  • :wrench: Flexible and extensible design
  • :bullseye: 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

Most Liked

egze

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

FedericoAlcantara

I just published a similar tool, with a somewhat different approach, but aiming at reducing the code boilerplate.

Check AuroraCTX

egze

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

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.

Where Next?

Popular in Libraries Top

marcuslankenau
I feel kind of stuck with the absence of a proper xml library for Elixir. Currently I use SweetXML which was ok for me more or less to pa...
New
michalmuskala
Hello everybody. I have just released Jason - a new JSON library. You might be wondering, why do we need a new library? The primary foc...
New
alisinabh
Hey everyone i’ve developed a library for Jalaali calendar for elixir which supports converting Gregorian dates to Jalaali and vice vers...
New
zorbash
I created Kitto a framework for dashboards inspired by Dashing. [demo] The distributed characteristics of Elixir and the low memory foo...
New
wmnnd
Hi there, for my project DBLSQD, I needed a file storage solution that is a bit more flexible than Arc. Because I thought others might f...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
KallDrexx
For a good number of months I've been working on creating a very basic RTMP live video streaming server. Now that I have a very, very ba...
New
maltoe
Hello! Came here to announce ChromicPDF, a pet project PDF generator I’ve been working on for the past few months. Why another PDF gener...
New
ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
381 12391 119
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Sub Categories:

We're in Beta

About us Mission Statement