7 releases (2 stable)
1.0.1 | Nov 6, 2023 |
---|---|
1.0.0 | Sep 14, 2022 |
0.1.4 | Jan 12, 2022 |
0.1.3 | Nov 10, 2021 |
0.1.0 | Aug 13, 2021 |
#1912 in Procedural macros
Used in diesel_filter
17KB
298 lines
Diesel Filter
Diesel filter is a quick way to add filters and pagination to your diesel models.
Works with Diesel
and Postgres
.
Crate features
rocket
DerivesFromForm
on the generated filter struct (See this example)actix
DerivesDeserialize
on the generated filter struct (See this example)pagination
Adds thePaginate
trait (See this example)serialize
withpagination
Adds thePaginatedPayload
trait that can directly be sent to your client
Usage & Examples
Cargo.toml
diesel_filter = { path = "../../diesel_filter/core", features = ["pagination", "serialize", "rocket"] }
Derive your struct with DieselFilter
and annotate the fields that will be used as filters.
The top level annotation #[diesel(table_name = db_table)]
is mandatory.
#[derive(Queryable, DieselFilter)]
#[diesel(table_name = projects)]
pub struct Project {
pub id: Uuid,
#[filter(substring, insensitive)]
pub name: String,
#[filter(substring)]
pub owner_email: String,
#[filter]
pub owner_id: Uuid,
pub created_at: NaiveDateTime,
}
The #[filter]
annotation can receive the kinds of filter you want to apply on it, for the moment, there is only substring
and insensitive
.
A struct for the filtering data will be generated with the name [YourStructName]Filters, e.g: ProjectFilters.
Two methods will be generated (let's keep Project
as an example):
pub fn filter<'a>(filters: &'a ProjectFilters) -> BoxedQuery<'a, Pg>
and
pub fn filtered(filters: &ProjectFilters, conn: &PgConnection) -> Result<Vec<Project>, Error>
The filter
method can be used in conjunction with other diesel methods like inner_join
and such.
Project::filter(&filters)
.inner_join(clients::table)
.select((projects::id, clients::name))
.load::<ProjectResponse>(conn)
With Rocket
With the rocket
feature, the generated struct can be obtained from the request query parameters (dot notation ?filters.name=xxx
)
use diesel_filter::PaginatedPayload;
#[get("/?<filters>")]
async fn index(filters: ClientFilters, conn: DbConn) -> Result<Json<PaginatedPayload<Client>>, Error> {
Ok(Json(
conn.run(move |conn| Client::filtered(&filters, conn))
.await?
.into(),
))
}
With Actix
With the actix
feature, the generated struct can be obtained from the request query parameters
N.B: unlike the rocket
integration, the query parameters must be sent unscopped. e.g ?field=xxx&other=1
use diesel_filter::PaginatedPayload;
#[get("/")]
async fn index(filters: web::Query(ClientFilters), conn: DbConn) -> Result<Json<PaginatedPayload<Client>>, Error> {
Ok(Json(
conn.run(move |conn| Client::filtered(&filters, conn))
.await?
.into(),
))
}
With Pagination
With the pagination
feature, you have access to the methods paginate
, per_page
and load_and_count
use diesel_filter::Paginate;
Project::filter(&filters)
.inner_join(clients::table)
.select((projects::id, clients::name))
.paginate(filters.page)
.per_page(filters.per_page)
.load_and_count::<ProjectResponse>(conn)
These are independent of the #[pagination]
annotation that you can add on your struct to add page
and per_page
to your generated filter struct and change the signature of the filtered
method.
#[derive(Queryable, DieselFilter)]
#[diesel(table_name = projects)]
#[pagination]
pub struct Project
To convert this into Json, with the feature flag serialize
you can use PaginatedPayload
.
pub struct PaginatedPayload<T> {
data: Vec<T>,
total: i64,
}
#[get("/?<filters>")]
async fn index(filters: ProjectFilters, conn: DbConn) -> Result<Json<PaginatedPayload<Project>>, Error> {
Ok(Json(
conn.run(move |conn| Project::filtered(&filters))
.await
.into(),
))
}
License
Diesel filter is licensed under either of the following, at your option:
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or https://opensource.org/licenses/MIT)
Dependencies
~1.5MB
~38K SLoC