Skip to content

Commit fc425a9

Browse files
committed
models/category: Convert subcategories() and parent_categories() to async fns
1 parent a5504d8 commit fc425a9

File tree

2 files changed

+72
-41
lines changed

2 files changed

+72
-41
lines changed

src/controllers/category.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::util::RequestUtils;
88
use crate::views::{EncodableCategory, EncodableCategoryWithSubcategories};
99
use axum::extract::Path;
1010
use axum::Json;
11-
use diesel::prelude::*;
11+
use diesel::QueryDsl;
1212
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
1313
use http::request::Parts;
1414
use serde_json::Value;
@@ -48,41 +48,43 @@ pub async fn index(app: AppState, req: Parts) -> AppResult<Json<Value>> {
4848

4949
/// Handles the `GET /categories/:category_id` route.
5050
pub async fn show(state: AppState, Path(slug): Path<String>) -> AppResult<Json<Value>> {
51-
let conn = state.db_read().await?;
52-
spawn_blocking(move || {
53-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
51+
use diesel_async::RunQueryDsl;
5452

55-
let cat: Category = Category::by_slug(&slug).first(conn)?;
56-
let subcats = cat
57-
.subcategories(conn)?
58-
.into_iter()
59-
.map(Category::into)
60-
.collect();
61-
let parents = cat
62-
.parent_categories(conn)?
63-
.into_iter()
64-
.map(Category::into)
65-
.collect();
66-
67-
let cat = EncodableCategory::from(cat);
68-
let cat_with_subcats = EncodableCategoryWithSubcategories {
69-
id: cat.id,
70-
category: cat.category,
71-
slug: cat.slug,
72-
description: cat.description,
73-
created_at: cat.created_at,
74-
crates_cnt: cat.crates_cnt,
75-
subcategories: subcats,
76-
parent_categories: parents,
77-
};
78-
79-
Ok(Json(json!({ "category": cat_with_subcats })))
80-
})
81-
.await
53+
let mut conn = state.db_read().await?;
54+
55+
let cat: Category = Category::by_slug(&slug).first(&mut conn).await?;
56+
let subcats = cat
57+
.subcategories(&mut conn)
58+
.await?
59+
.into_iter()
60+
.map(Category::into)
61+
.collect();
62+
let parents = cat
63+
.parent_categories(&mut conn)
64+
.await?
65+
.into_iter()
66+
.map(Category::into)
67+
.collect();
68+
69+
let cat = EncodableCategory::from(cat);
70+
let cat_with_subcats = EncodableCategoryWithSubcategories {
71+
id: cat.id,
72+
category: cat.category,
73+
slug: cat.slug,
74+
description: cat.description,
75+
created_at: cat.created_at,
76+
crates_cnt: cat.crates_cnt,
77+
subcategories: subcats,
78+
parent_categories: parents,
79+
};
80+
81+
Ok(Json(json!({ "category": cat_with_subcats })))
8282
}
8383

8484
/// Handles the `GET /category_slugs` route.
8585
pub async fn slugs(state: AppState) -> AppResult<Json<Value>> {
86+
use diesel::RunQueryDsl;
87+
8688
let conn = state.db_read().await?;
8789
spawn_blocking(move || {
8890
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();

src/models/category.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use chrono::NaiveDateTime;
2-
use diesel::{self, *};
2+
use diesel::{
3+
delete, dsl, insert_into, sql_query, ExpressionMethods, QueryDsl, QueryResult,
4+
TextExpressionMethods,
5+
};
6+
use diesel_async::AsyncPgConnection;
37

48
use crate::models::Crate;
59
use crate::schema::*;
@@ -47,6 +51,7 @@ impl Category {
4751
crate_id: i32,
4852
slugs: &[&str],
4953
) -> QueryResult<Vec<String>> {
54+
use diesel::RunQueryDsl;
5055
conn.transaction(|conn| {
5156
let categories: Vec<Category> = categories::table
5257
.filter(categories::slug.eq_any(slugs))
@@ -77,6 +82,7 @@ impl Category {
7782
}
7883

7984
pub fn count_toplevel(conn: &mut impl Conn) -> QueryResult<i64> {
85+
use diesel::RunQueryDsl;
8086
categories::table
8187
.filter(categories::category.not_like("%::%"))
8288
.count()
@@ -90,6 +96,7 @@ impl Category {
9096
offset: i64,
9197
) -> QueryResult<Vec<Category>> {
9298
use diesel::sql_types::Int8;
99+
use diesel::RunQueryDsl;
93100

94101
let sort_sql = match sort {
95102
"crates" => "ORDER BY crates_cnt DESC",
@@ -104,24 +111,31 @@ impl Category {
104111
.load(conn)
105112
}
106113

107-
pub fn subcategories(&self, conn: &mut impl Conn) -> QueryResult<Vec<Category>> {
114+
pub async fn subcategories(&self, conn: &mut AsyncPgConnection) -> QueryResult<Vec<Category>> {
108115
use diesel::sql_types::Text;
116+
use diesel_async::RunQueryDsl;
109117

110118
sql_query(include_str!("../subcategories.sql"))
111119
.bind::<Text, _>(&self.category)
112120
.load(conn)
121+
.await
113122
}
114123

115124
/// Gathers the parent categories from the top-level Category to the direct parent of this Category.
116125
/// Returns categories as a Vector in order of traversal, not including this Category.
117126
/// The intention is to be able to have slugs or parent categories arrayed in order, to
118127
/// offer the frontend, for examples, slugs to create links to each parent category in turn.
119-
pub fn parent_categories(&self, conn: &mut impl Conn) -> QueryResult<Vec<Category>> {
128+
pub async fn parent_categories(
129+
&self,
130+
conn: &mut AsyncPgConnection,
131+
) -> QueryResult<Vec<Category>> {
120132
use diesel::sql_types::Text;
133+
use diesel_async::RunQueryDsl;
121134

122135
sql_query(include_str!("../parent_categories.sql"))
123136
.bind::<Text, _>(&self.slug)
124137
.load(conn)
138+
.await
125139
}
126140
}
127141

@@ -139,10 +153,13 @@ pub struct NewCategory<'a> {
139153
mod tests {
140154
use super::*;
141155
use crate::test_util::test_db_connection;
156+
use crates_io_test_db::TestDatabase;
157+
use diesel_async::AsyncConnection;
142158

143159
#[test]
144160
fn category_toplevel_excludes_subcategories() {
145161
use self::categories;
162+
use diesel::RunQueryDsl;
146163
let (_test_db, conn) = &mut test_db_connection();
147164
insert_into(categories::table)
148165
.values(&vec![
@@ -174,6 +191,7 @@ mod tests {
174191
#[test]
175192
fn category_toplevel_orders_by_crates_cnt_when_sort_given() {
176193
use self::categories;
194+
use diesel::RunQueryDsl;
177195

178196
let new_cat = |category, slug, crates_cnt| {
179197
(
@@ -209,6 +227,7 @@ mod tests {
209227
#[test]
210228
fn category_toplevel_applies_limit_and_offset() {
211229
use self::categories;
230+
use diesel::RunQueryDsl;
212231
let (_test_db, conn) = &mut test_db_connection();
213232
insert_into(categories::table)
214233
.values(&vec![
@@ -244,6 +263,7 @@ mod tests {
244263
#[test]
245264
fn category_toplevel_includes_subcategories_in_crate_cnt() {
246265
use self::categories;
266+
use diesel::RunQueryDsl;
247267

248268
let new_cat = |category, slug, crates_cnt| {
249269
(
@@ -282,6 +302,7 @@ mod tests {
282302
#[test]
283303
fn category_toplevel_applies_limit_and_offset_after_grouping() {
284304
use self::categories;
305+
use diesel::RunQueryDsl;
285306

286307
let new_cat = |category, slug, crates_cnt| {
287308
(
@@ -321,9 +342,10 @@ mod tests {
321342
assert_eq!(expected, cats);
322343
}
323344

324-
#[test]
325-
fn category_parent_categories_includes_path_to_node_with_count() {
345+
#[tokio::test]
346+
async fn category_parent_categories_includes_path_to_node_with_count() {
326347
use self::categories;
348+
use diesel_async::RunQueryDsl;
327349

328350
let new_cat = |category, slug, crates_cnt| {
329351
(
@@ -333,7 +355,9 @@ mod tests {
333355
)
334356
};
335357

336-
let (_test_db, conn) = &mut test_db_connection();
358+
let test_db = TestDatabase::new();
359+
let mut conn = AsyncPgConnection::establish(test_db.url()).await.unwrap();
360+
337361
insert_into(categories::table)
338362
.values(&vec![
339363
new_cat("Cat 1", "cat1", 1),
@@ -345,12 +369,17 @@ mod tests {
345369
new_cat("Cat 2::Sub 2", "cat2::sub2", 5),
346370
new_cat("Cat 3", "cat3", 200),
347371
])
348-
.execute(conn)
372+
.execute(&mut conn)
373+
.await
374+
.unwrap();
375+
376+
let cat: Category = Category::by_slug("cat1::sub1")
377+
.first(&mut conn)
378+
.await
349379
.unwrap();
350380

351-
let cat: Category = Category::by_slug("cat1::sub1").first(conn).unwrap();
352-
let subcats = cat.subcategories(conn).unwrap();
353-
let parents = cat.parent_categories(conn).unwrap();
381+
let subcats = cat.subcategories(&mut conn).await.unwrap();
382+
let parents = cat.parent_categories(&mut conn).await.unwrap();
354383

355384
assert_eq!(parents.len(), 1);
356385
assert_eq!(parents[0].slug, "cat1");

0 commit comments

Comments
 (0)