upvoters/src/votes/repository.rs

117 lines
3.5 KiB
Rust
Raw Normal View History

use anyhow::Result;
use sqlx::{PgPool, query, query_as, query_scalar};
use uuid::Uuid;
use crate::votes::model::BestSlugs;
pub async fn insert_new_vote(slug: &str, voter_id: &Uuid, db: &PgPool) -> Result<()> {
query("insert into votes (slug, voter_id) values ($1, $2)")
.bind(slug)
.bind(voter_id)
.execute(db)
.await?;
Ok(())
}
pub async fn get_vote_count_for_slug(slug: &str, db: &PgPool) -> Result<i64> {
let count: i64 = query_scalar("select count(*) from votes where slug=$1")
.bind(slug)
.fetch_one(db)
.await?;
Ok(count)
}
pub async fn get_top_n_slugs(n: i64, db: &PgPool) -> Result<Vec<BestSlugs>> {
if n > 0 {
let top_slugs = query_as::<_, BestSlugs>(
r#"select slug, count(*) AS vote_count
from votes
group by slug
order by vote_count desc
limit $1
"#,
)
.bind(n)
.fetch_all(db)
.await?;
Ok(top_slugs)
} else {
Ok(vec![])
}
}
pub async fn delete_vote(slug: &str, voter_id: &Uuid, db: &PgPool) -> Result<()> {
query("delete from votes where slug=$1 and voter_id=$2")
.bind(slug)
.bind(voter_id)
.execute(db)
.await?;
Ok(())
}
#[cfg(test)]
mod postgres_tests {
use sqlx::PgPool;
use uuid::Uuid;
use crate::{
test_helpers::db::test_pool,
votes::repository::{delete_vote, get_top_n_slugs, get_vote_count_for_slug, insert_new_vote},
};
fn test_votes() -> [(&'static str, Uuid); 9] {
[
("blog_post1", Uuid::from_u128(0x1)),
("blog_post1", Uuid::from_u128(0x2)),
("blog_post2", Uuid::from_u128(0x3)),
("blog_post2", Uuid::from_u128(0x4)),
("blog_post3", Uuid::from_u128(0x5)),
("blog_post3", Uuid::from_u128(0x6)),
("blog_post1", Uuid::from_u128(0x7)),
("blog_post1", Uuid::from_u128(0x8)),
("blog_post3", Uuid::from_u128(0x9)),
]
}
async fn cleanup(db: &PgPool) {
for (slug, voter_id) in test_votes() {
delete_vote(slug, &voter_id, db).await.unwrap()
}
}
#[tokio::test]
#[ignore]
pub async fn postgres_tests() {
let db = test_pool().await;
cleanup(&db).await;
let votes = test_votes();
for (slug, voter_id) in votes.iter() {
insert_new_vote(slug, voter_id, &db)
.await
.expect("Insertions to db failed");
}
assert_eq!(get_vote_count_for_slug("blog_post1", &db).await.unwrap(), 4);
assert_eq!(get_vote_count_for_slug("blog_post2", &db).await.unwrap(), 2);
assert_eq!(get_vote_count_for_slug("blog_post3", &db).await.unwrap(), 3);
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
assert_eq!(top_2[0].slug, "blog_post1");
assert_eq!(top_2[1].slug, "blog_post3");
delete_vote(votes[4].0, &votes[4].1, &db).await.unwrap();
delete_vote(votes[5].0, &votes[5].1, &db).await.unwrap();
assert_eq!(get_vote_count_for_slug("blog_post1", &db).await.unwrap(), 4);
assert_eq!(get_vote_count_for_slug("blog_post2", &db).await.unwrap(), 2);
assert_eq!(get_vote_count_for_slug("blog_post3", &db).await.unwrap(), 1);
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
assert_eq!(top_2[0].slug, "blog_post1");
assert_eq!(top_2[1].slug, "blog_post2");
cleanup(&db).await;
}
}