Decode list_ranked_articles rows via a From<Row> impl
All checks were successful
CI / check (pull_request) Successful in 1m58s
CI / test (pull_request) Successful in 2m28s
CI / audit (pull_request) Successful in 10s

Replaces the inline .map() closure with From<Row> for
RankedArticleRow, separating "what a raw SQLite row looks like" from
the query itself.
This commit is contained in:
Austin Schaefer 2026-09-03 21:26:56 +02:00
parent e70909af47
commit cc79f59a7d

View file

@ -108,7 +108,6 @@ impl Db {
if let Some(feed_id) = feed_id { if let Some(feed_id) = feed_id {
query = query.filter(dsl::feed_id.eq(feed_id.to_string())); query = query.filter(dsl::feed_id.eq(feed_id.to_string()));
} }
type Row = (String, String, String, String, String, String, Option<f32>);
let rows: Vec<Row> = query let rows: Vec<Row> = query
.order(dsl::final_score.desc()) .order(dsl::final_score.desc())
.limit(limit) .limit(limit)
@ -123,10 +122,17 @@ impl Db {
)) ))
.load(&mut conn) .load(&mut conn)
.await?; .await?;
Ok(rows Ok(rows.into_iter().map(RankedArticleRow::from).collect())
.into_iter() }
.map( }
|(id, feed_id, title, url, summary, topics_json, final_score)| RankedArticleRow {
/// Raw shape of one `list_ranked_articles` row as loaded from SQLite —
/// `topics` is still the JSON string column, not yet decoded.
type Row = (String, String, String, String, String, String, Option<f32>);
impl From<Row> for RankedArticleRow {
fn from((id, feed_id, title, url, summary, topics_json, final_score): Row) -> Self {
Self {
id, id,
feed_id, feed_id,
title, title,
@ -134,9 +140,7 @@ impl Db {
summary, summary,
topics: serde_json::from_str(&topics_json).unwrap_or_default(), topics: serde_json::from_str(&topics_json).unwrap_or_default(),
final_score, final_score,
}, }
)
.collect())
} }
} }