--- /dev/null
+use crate::schema::user_aggregates;
+use diesel::{result::Error, *};
+use serde::Serialize;
+
+#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
+#[table_name = "user_aggregates"]
+pub struct UserAggregates {
+ pub id: i32,
+ pub user_id: i32,
+ pub post_count: i64,
+ pub post_score: i64,
+ pub comment_count: i64,
+ pub comment_score: i64,
+}
+
+impl UserAggregates {
+ pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
+ user_aggregates::table.find(id).first::<Self>(conn)
+ }
+}
+
+// TODO add unit tests, to make sure triggers are working
use crate::{
- schema::user_,
+ aggregates::user_aggregates::UserAggregates,
+ schema::{user_, user_aggregates},
user::{UserSafe, User_},
};
use diesel::{result::Error, *};
#[derive(Debug, Serialize, Clone)]
pub struct UserViewSafe {
pub user: UserSafe,
- // TODO
- // pub number_of_posts: i64,
- // pub post_score: i64,
- // pub number_of_comments: i64,
- // pub comment_score: i64,
+ pub counts: UserAggregates,
}
+#[derive(Debug, Serialize, Clone)]
pub struct UserViewDangerous {
pub user: User_,
- // TODO
- // pub number_of_posts: i64,
- // pub post_score: i64,
- // pub number_of_comments: i64,
- // pub comment_score: i64,
+ pub counts: UserAggregates,
}
impl UserViewDangerous {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
- let user = user_::table.find(id).first::<User_>(conn)?;
- Ok(Self { user })
+ let (user, counts) = user_::table
+ .find(id)
+ .inner_join(user_aggregates::table)
+ .first::<(User_, UserAggregates)>(conn)?;
+ Ok(Self { user, counts })
}
}
impl UserViewSafe {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
- let user = user_::table.find(id).first::<User_>(conn)?.to_safe();
- Ok(Self { user })
+ let (user, counts) = user_::table
+ .find(id)
+ .inner_join(user_aggregates::table)
+ .first::<(User_, UserAggregates)>(conn)?;
+ Ok(Self {
+ user: user.to_safe(),
+ counts,
+ })
}
pub fn admins(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let admins = user_::table
- // TODO do joins here
+ .inner_join(user_aggregates::table)
.filter(user_::admin.eq(true))
.order_by(user_::published)
- .load::<User_>(conn)?;
+ .load::<(User_, UserAggregates)>(conn)?;
Ok(vec_to_user_view_safe(admins))
}
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let banned = user_::table
- // TODO do joins here
+ .inner_join(user_aggregates::table)
.filter(user_::banned.eq(true))
- .load::<User_>(conn)?;
+ .load::<(User_, UserAggregates)>(conn)?;
Ok(vec_to_user_view_safe(banned))
}
}
-fn vec_to_user_view_safe(users: Vec<User_>) -> Vec<UserViewSafe> {
+fn vec_to_user_view_safe(users: Vec<(User_, UserAggregates)>) -> Vec<UserViewSafe> {
users
.iter()
- .map(|a| UserViewSafe { user: a.to_safe() })
+ .map(|a| UserViewSafe {
+ user: a.0.to_safe(),
+ counts: a.1.to_owned(),
+ })
.collect::<Vec<UserViewSafe>>()
}
as $$
begin
IF (TG_OP = 'INSERT') THEN
+ -- TODO not sure if this is working right
+ -- Need to get the post creator, not the voter
update user_aggregates
- set post_score = post_score + NEW.score where user_id = NEW.user_id;
+ set post_score = post_score + NEW.score
+ from post_like pl join post p on p.id = pl.post_id
+ where p.id = NEW.post_id and p.creator_id = NEW.user_id;
ELSIF (TG_OP = 'DELETE') THEN
update user_aggregates
- set post_score = post_score - OLD.score where user_id = OLD.user_id;
+ set post_score = post_score - OLD.score
+ from post_like pl join post p on p.id = pl.post_id
+ where p.id = OLD.post_id and p.creator_id = OLD.user_id;
END IF;
return null;
end $$;
as $$
begin
IF (TG_OP = 'INSERT') THEN
+ -- Need to get the post creator, not the voter
update user_aggregates
- set comment_score = comment_score + NEW.score where user_id = NEW.user_id;
+ set comment_score = comment_score + NEW.score
+ from comment_like pl join comment p on p.id = pl.comment_id
+ where p.id = NEW.comment_id and p.creator_id = NEW.user_id;
ELSIF (TG_OP = 'DELETE') THEN
update user_aggregates
- set comment_score = comment_score - OLD.score where user_id = OLD.user_id;
+ set comment_score = comment_score - OLD.score
+ from comment_like pl join comment p on p.id = pl.comment_id
+ where p.id = OLD.comment_id and p.creator_id = OLD.user_id;
END IF;
return null;
end $$;