-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add filter() fn, update pagination() fn #103
Changes from all commits
54f62cf
7d428b4
8afaa2e
3acf838
9bf6b67
f57471c
7518fa1
c049d34
92697c8
8fc15f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,7 +215,7 @@ impl<'a> Struct<'a> { | |
/// Render the full struct | ||
fn render(&mut self) { | ||
let ty = self.ty; | ||
let table = &self.table; | ||
let table = self.table; | ||
|
||
let primary_keys: Vec<String> = table.primary_key_column_names(); | ||
|
||
|
@@ -423,12 +423,13 @@ impl {struct_name} {{ | |
|
||
buffer.push_str(&format!(r##" | ||
/// Paginates through the table where page is a 0-based index (i.e. page 0 is the first page) | ||
pub{async_keyword} fn paginate(db: &mut ConnectionType, page: i64, page_size: i64) -> QueryResult<PaginationResult<Self>> {{ | ||
pub{async_keyword} fn paginate(db: &mut ConnectionType, page: i64, page_size: i64, filter: {struct_name}Filter) -> QueryResult<PaginationResult<Self>> {{ | ||
use {schema_path}{table_name}::dsl::*; | ||
|
||
let page_size = if page_size < 1 {{ 1 }} else {{ page_size }}; | ||
let total_items = {table_name}.count().get_result(db){await_keyword}?; | ||
let items = {table_name}.limit(page_size).offset(page * page_size).load::<Self>(db){await_keyword}?; | ||
let page = page.max(0); | ||
let page_size = page_size.max(1); | ||
let total_items = Self::filter(filter.clone()).count().get_result(db)?; | ||
let items = Self::filter(filter).limit(page_size).offset(page * page_size).load::<Self>(db){await_keyword}?; | ||
|
||
Ok(PaginationResult {{ | ||
items, | ||
|
@@ -441,6 +442,51 @@ impl {struct_name} {{ | |
}} | ||
"##)); | ||
|
||
// Table::filter() helper fn | ||
{ | ||
let diesel_backend = &config.diesel_backend; | ||
let filters = table | ||
.columns | ||
.iter() | ||
.map(|column| { | ||
let column_name = column.name.to_string(); | ||
format!( | ||
r##" | ||
if let Some(filter_{column_name}) = filter.{column_name}.clone() {{ | ||
query = query.filter({schema_path}{table_name}::{column_name}.eq(filter_{column_name})); | ||
}}"## | ||
) | ||
}) | ||
Comment on lines
+451
to
+459
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks quite redundant, is there not better option? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. feel free to suggest changes. This new filter() API is an experiment I want to run and play with. We might want to remove it in the future as intellisense gets better and better around macros. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i had already looked, but there does not seem to be a diesel helper trait which would have a Update-like struct be the filter, something as simple as |
||
.collect::<Vec<_>>() | ||
.join(""); | ||
buffer.push_str(&format!( | ||
r##" | ||
/// A utility function to help build custom search queries | ||
/// | ||
/// Example: | ||
hasezoey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// | ||
/// ``` | ||
/// // create a filter for completed todos | ||
/// let query = Todo::filter(TodoFilter {{ | ||
/// completed: Some(true), | ||
/// ..Default::default() | ||
/// }}); | ||
/// | ||
/// // delete completed todos | ||
/// diesel::delete(query).execute(db)?; | ||
/// ``` | ||
pub fn filter<'a>( | ||
filter: {struct_name}Filter, | ||
) -> {schema_path}{table_name}::BoxedQuery<'a, {diesel_backend}> {{ | ||
let mut query = {schema_path}{table_name}::table.into_boxed(); | ||
{filters} | ||
|
||
query | ||
}} | ||
"## | ||
)); | ||
} | ||
|
||
// TODO: If primary key columns are attached to the form struct (not optionally) | ||
// then don't require item_id_params (otherwise it'll be duplicated) | ||
|
||
|
@@ -470,10 +516,36 @@ impl {struct_name} {{ | |
)); | ||
|
||
buffer.push_str( | ||
r##" | ||
}"##, | ||
r#" | ||
}"#, | ||
); | ||
|
||
// generate filter struct for filter() helper function | ||
{ | ||
let filter_fields = table | ||
.columns | ||
.iter() | ||
.map(|column| { | ||
let struct_field = StructField::from(column); | ||
format!( | ||
"pub {column_name}: Option<{column_type}>,", | ||
column_name = struct_field.name, | ||
column_type = struct_field.to_rust_type() | ||
) | ||
}) | ||
.collect::<Vec<_>>() | ||
.join("\n "); | ||
|
||
buffer.push_str(&format!( | ||
r##" | ||
#[derive(Debug, Default, Clone)] | ||
pub struct {struct_name}Filter {{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should probably be a new structtype There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's leave this for now as it's an experimental API that needs more iterations before we solidify it as a core struct. |
||
{filter_fields} | ||
}} | ||
"## | ||
)); | ||
} | ||
|
||
buffer | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this block should likely be its own function to keep the functions smaller, but this can be delayed until we refactor this (see #105)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, I’ll take a look at this later and try to rebase 🙌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless you want to delay this PR, i will hold off on merging other stuff (even if approved) so you can get this (and possibly your other PR's) merged without having to rebase it often
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @hasezoey, I really appreciate your consideration 🤗
Please do approve this PR if you think it's generally acceptable. That way, I can rebase and merge later without having to stop any others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i take this as meaning you have not rebased yet, so i will merge the other standing (approved) PRs to not have to wait, after that i will approve