I'd like to be able to keep predicates for filtering my tables somewhere in one place and give them nice names. E.g.: instead of writing something like
let post = posts
.filter(published.eq(true).and(id.eq(5))
...
I'd like to have a function like this:
fn published_with_id(n: i64) -> (WHAT HERE?) {
published.eq(true).and(id.eq(n))
}
...
let post = posts.filter(published_with_id(5))
However, when I try to compile that code, I get a suggestion to declare the return type of the predicate function as something long and with something quite long indeed: diesel::expression::grouped::Grouped<diesel::expression::operators::And<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<columns::published, diesel::expression::bound::Bound<diesel::sql_types::Bool, bool>>>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<columns::id, i64>>>>
Is there a way to annotate it with a reasonable return type? Or is there a better way to keep all my predicates in one place?
There is a way to specify that a function returns something implementing a trait, without naming a concrete type. It's called return position impl trait (RPIT), and lucky for you you have a common trait, as all query builder combinators defined in diesel::expression
implement Expression
.
So the solution is to use impl Expression
as the return type:
fn published_with_id(n: i64) -> impl Expression {
published.eq(true).and(id.eq(n))
}