Adding a viewtovec trait.

This commit is contained in:
Dessalines 2020-12-10 20:39:42 -05:00
parent eef93440d0
commit afc79ce0e3
6 changed files with 116 additions and 94 deletions

View File

@ -2,6 +2,7 @@ use crate::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
schema::{community, community_follower, user_}, schema::{community, community_follower, user_},
user::{UserSafe, User_}, user::{UserSafe, User_},
views::ViewToVec,
ToSafe, ToSafe,
}; };
use diesel::{result::Error, *}; use diesel::{result::Error, *};
@ -13,6 +14,8 @@ pub struct CommunityFollowerView {
pub follower: UserSafe, pub follower: UserSafe,
} }
type CommunityFollowerViewTuple = (CommunitySafe, UserSafe);
impl CommunityFollowerView { impl CommunityFollowerView {
pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result<Vec<Self>, Error> { pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result<Vec<Self>, Error> {
let res = community_follower::table let res = community_follower::table
@ -21,9 +24,9 @@ impl CommunityFollowerView {
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((Community::safe_columns_tuple(), User_::safe_columns_tuple()))
.filter(community_follower::community_id.eq(for_community_id)) .filter(community_follower::community_id.eq(for_community_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<(CommunitySafe, UserSafe)>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;
Ok(to_vec(res)) Ok(Self::to_vec(res))
} }
pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result<Vec<Self>, Error> { pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result<Vec<Self>, Error> {
@ -33,18 +36,21 @@ impl CommunityFollowerView {
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((Community::safe_columns_tuple(), User_::safe_columns_tuple()))
.filter(community_follower::user_id.eq(for_user_id)) .filter(community_follower::user_id.eq(for_user_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<(CommunitySafe, UserSafe)>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;
Ok(to_vec(res)) Ok(Self::to_vec(res))
} }
} }
fn to_vec(users: Vec<(CommunitySafe, UserSafe)>) -> Vec<CommunityFollowerView> { impl ViewToVec for CommunityFollowerView {
users type DbTuple = CommunityFollowerViewTuple;
.iter() fn to_vec(users: Vec<Self::DbTuple>) -> Vec<Self> {
.map(|a| CommunityFollowerView { users
community: a.0.to_owned(), .iter()
follower: a.1.to_owned(), .map(|a| Self {
}) community: a.0.to_owned(),
.collect::<Vec<CommunityFollowerView>>() follower: a.1.to_owned(),
})
.collect::<Vec<Self>>()
}
} }

View File

@ -2,6 +2,7 @@ use crate::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
schema::{community, community_moderator, user_}, schema::{community, community_moderator, user_},
user::{UserSafe, User_}, user::{UserSafe, User_},
views::ViewToVec,
ToSafe, ToSafe,
}; };
use diesel::{result::Error, *}; use diesel::{result::Error, *};
@ -13,6 +14,8 @@ pub struct CommunityModeratorView {
pub moderator: UserSafe, pub moderator: UserSafe,
} }
type CommunityModeratorViewTuple = (CommunitySafe, UserSafe);
impl CommunityModeratorView { impl CommunityModeratorView {
pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result<Vec<Self>, Error> { pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result<Vec<Self>, Error> {
let res = community_moderator::table let res = community_moderator::table
@ -21,9 +24,9 @@ impl CommunityModeratorView {
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((Community::safe_columns_tuple(), User_::safe_columns_tuple()))
.filter(community_moderator::community_id.eq(for_community_id)) .filter(community_moderator::community_id.eq(for_community_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<(CommunitySafe, UserSafe)>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;
Ok(to_vec(res)) Ok(Self::to_vec(res))
} }
pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result<Vec<Self>, Error> { pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result<Vec<Self>, Error> {
@ -33,18 +36,21 @@ impl CommunityModeratorView {
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((Community::safe_columns_tuple(), User_::safe_columns_tuple()))
.filter(community_moderator::user_id.eq(for_user_id)) .filter(community_moderator::user_id.eq(for_user_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<(CommunitySafe, UserSafe)>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;
Ok(to_vec(res)) Ok(Self::to_vec(res))
} }
} }
fn to_vec(users: Vec<(CommunitySafe, UserSafe)>) -> Vec<CommunityModeratorView> { impl ViewToVec for CommunityModeratorView {
users type DbTuple = CommunityModeratorViewTuple;
.iter() fn to_vec(community_moderators: Vec<Self::DbTuple>) -> Vec<Self> {
.map(|a| CommunityModeratorView { community_moderators
community: a.0.to_owned(), .iter()
moderator: a.1.to_owned(), .map(|a| Self {
}) community: a.0.to_owned(),
.collect::<Vec<CommunityModeratorView>>() moderator: a.1.to_owned(),
})
.collect::<Vec<Self>>()
}
} }

View File

@ -7,6 +7,7 @@ use crate::{
limit_and_offset, limit_and_offset,
schema::{category, community, community_aggregates, community_follower, user_}, schema::{category, community, community_aggregates, community_follower, user_},
user::{UserSafe, User_}, user::{UserSafe, User_},
views::ViewToVec,
MaybeOptional, MaybeOptional,
SortType, SortType,
ToSafe, ToSafe,
@ -23,6 +24,14 @@ pub struct CommunityView {
pub counts: CommunityAggregates, pub counts: CommunityAggregates,
} }
type CommunityViewTuple = (
CommunitySafe,
UserSafe,
Category,
CommunityAggregates,
Option<CommunityFollower>,
);
impl CommunityView { impl CommunityView {
pub fn read( pub fn read(
conn: &PgConnection, conn: &PgConnection,
@ -51,13 +60,7 @@ impl CommunityView {
community_aggregates::all_columns, community_aggregates::all_columns,
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
)) ))
.first::<( .first::<CommunityViewTuple>(conn)?;
CommunitySafe,
UserSafe,
Category,
CommunityAggregates,
Option<CommunityFollower>,
)>(conn)?;
Ok(CommunityView { Ok(CommunityView {
community, community,
@ -270,35 +273,24 @@ impl<'a> CommunityQueryBuilder<'a> {
.offset(offset) .offset(offset)
.filter(community::removed.eq(false)) .filter(community::removed.eq(false))
.filter(community::deleted.eq(false)) .filter(community::deleted.eq(false))
.load::<( .load::<CommunityViewTuple>(self.conn)?;
CommunitySafe,
UserSafe,
Category,
CommunityAggregates,
Option<CommunityFollower>,
)>(self.conn)?;
Ok(to_vec(res)) Ok(CommunityView::to_vec(res))
} }
} }
fn to_vec( impl ViewToVec for CommunityView {
users: Vec<( type DbTuple = CommunityViewTuple;
CommunitySafe, fn to_vec(communities: Vec<Self::DbTuple>) -> Vec<Self> {
UserSafe, communities
Category, .iter()
CommunityAggregates, .map(|a| Self {
Option<CommunityFollower>, community: a.0.to_owned(),
)>, creator: a.1.to_owned(),
) -> Vec<CommunityView> { category: a.2.to_owned(),
users counts: a.3.to_owned(),
.iter() subscribed: a.4.is_some(),
.map(|a| CommunityView { })
community: a.0.to_owned(), .collect::<Vec<Self>>()
creator: a.1.to_owned(), }
category: a.2.to_owned(),
counts: a.3.to_owned(),
subscribed: a.4.is_some(),
})
.collect::<Vec<CommunityView>>()
} }

View File

@ -5,3 +5,10 @@ pub mod community_view;
pub mod post_view; pub mod post_view;
pub mod site_view; pub mod site_view;
pub mod user_view; pub mod user_view;
pub(crate) trait ViewToVec {
type DbTuple;
fn to_vec(tuple: Vec<Self::DbTuple>) -> Vec<Self>
where
Self: Sized;
}

View File

@ -17,6 +17,7 @@ use crate::{
user_, user_,
}, },
user::{UserSafe, User_}, user::{UserSafe, User_},
views::ViewToVec,
ListingType, ListingType,
MaybeOptional, MaybeOptional,
SortType, SortType,
@ -38,7 +39,7 @@ pub struct PostView {
pub my_vote: Option<i16>, // Left join to PostLike pub my_vote: Option<i16>, // Left join to PostLike
} }
type OutputTuple = ( type PostViewTuple = (
Post, Post,
UserSafe, UserSafe,
CommunitySafe, CommunitySafe,
@ -107,7 +108,7 @@ impl PostView {
post_read::all_columns.nullable(), post_read::all_columns.nullable(),
post_like::score.nullable(), post_like::score.nullable(),
)) ))
.first::<OutputTuple>(conn)?; .first::<PostViewTuple>(conn)?;
Ok(PostView { Ok(PostView {
post, post,
@ -551,26 +552,28 @@ impl<'a> PostQueryBuilder<'a> {
.filter(post::deleted.eq(false)) .filter(post::deleted.eq(false))
.filter(community::removed.eq(false)) .filter(community::removed.eq(false))
.filter(community::deleted.eq(false)) .filter(community::deleted.eq(false))
.load::<OutputTuple>(self.conn)?; .load::<PostViewTuple>(self.conn)?;
Ok(to_vec(res)) Ok(PostView::to_vec(res))
} }
} }
// TODO turn this into a trait with an associated type impl ViewToVec for PostView {
fn to_vec(posts: Vec<OutputTuple>) -> Vec<PostView> { type DbTuple = PostViewTuple;
posts fn to_vec(posts: Vec<Self::DbTuple>) -> Vec<Self> {
.iter() posts
.map(|a| PostView { .iter()
post: a.0.to_owned(), .map(|a| Self {
creator: a.1.to_owned(), post: a.0.to_owned(),
community: a.2.to_owned(), creator: a.1.to_owned(),
counts: a.3.to_owned(), community: a.2.to_owned(),
subscribed: a.4.is_some(), counts: a.3.to_owned(),
banned_from_community: a.5.is_some(), subscribed: a.4.is_some(),
saved: a.6.is_some(), banned_from_community: a.5.is_some(),
read: a.7.is_some(), saved: a.6.is_some(),
my_vote: a.8, read: a.7.is_some(),
}) my_vote: a.8,
.collect::<Vec<PostView>>() })
.collect::<Vec<Self>>()
}
} }

View File

@ -4,6 +4,7 @@ use crate::{
limit_and_offset, limit_and_offset,
schema::{user_, user_aggregates}, schema::{user_, user_aggregates},
user::{UserSafe, User_}, user::{UserSafe, User_},
views::ViewToVec,
MaybeOptional, MaybeOptional,
SortType, SortType,
ToSafe, ToSafe,
@ -17,18 +18,22 @@ pub struct UserViewSafe {
pub counts: UserAggregates, pub counts: UserAggregates,
} }
type UserViewSafeTuple = (UserSafe, UserAggregates);
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct UserViewDangerous { pub struct UserViewDangerous {
pub user: User_, pub user: User_,
pub counts: UserAggregates, pub counts: UserAggregates,
} }
type UserViewDangerousTuple = (User_, UserAggregates);
impl UserViewDangerous { impl UserViewDangerous {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
let (user, counts) = user_::table let (user, counts) = user_::table
.find(id) .find(id)
.inner_join(user_aggregates::table) .inner_join(user_aggregates::table)
.first::<(User_, UserAggregates)>(conn)?; .first::<UserViewDangerousTuple>(conn)?;
Ok(Self { user, counts }) Ok(Self { user, counts })
} }
} }
@ -39,7 +44,7 @@ impl UserViewSafe {
.find(id) .find(id)
.inner_join(user_aggregates::table) .inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns)) .select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.first::<(UserSafe, UserAggregates)>(conn)?; .first::<UserViewSafeTuple>(conn)?;
Ok(Self { user, counts }) Ok(Self { user, counts })
} }
@ -49,9 +54,9 @@ impl UserViewSafe {
.select((User_::safe_columns_tuple(), user_aggregates::all_columns)) .select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::admin.eq(true)) .filter(user_::admin.eq(true))
.order_by(user_::published) .order_by(user_::published)
.load::<(UserSafe, UserAggregates)>(conn)?; .load::<UserViewSafeTuple>(conn)?;
Ok(to_vec(admins)) Ok(Self::to_vec(admins))
} }
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> { pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
@ -59,9 +64,9 @@ impl UserViewSafe {
.inner_join(user_aggregates::table) .inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns)) .select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::banned.eq(true)) .filter(user_::banned.eq(true))
.load::<(UserSafe, UserAggregates)>(conn)?; .load::<UserViewSafeTuple>(conn)?;
Ok(to_vec(banned)) Ok(Self::to_vec(banned))
} }
} }
@ -186,18 +191,21 @@ impl<'a> UserQueryBuilder<'a> {
let (limit, offset) = limit_and_offset(self.page, self.limit); let (limit, offset) = limit_and_offset(self.page, self.limit);
query = query.limit(limit).offset(offset); query = query.limit(limit).offset(offset);
let res = query.load::<(UserSafe, UserAggregates)>(self.conn)?; let res = query.load::<UserViewSafeTuple>(self.conn)?;
Ok(to_vec(res)) Ok(UserViewSafe::to_vec(res))
} }
} }
fn to_vec(users: Vec<(UserSafe, UserAggregates)>) -> Vec<UserViewSafe> { impl ViewToVec for UserViewSafe {
users type DbTuple = UserViewSafeTuple;
.iter() fn to_vec(users: Vec<Self::DbTuple>) -> Vec<Self> {
.map(|a| UserViewSafe { users
user: a.0.to_owned(), .iter()
counts: a.1.to_owned(), .map(|a| Self {
}) user: a.0.to_owned(),
.collect::<Vec<UserViewSafe>>() counts: a.1.to_owned(),
})
.collect::<Vec<Self>>()
}
} }