]> Untitled Git - lemmy.git/commitdiff
Use builder pattern for views
authorDessalines <tyhou13@gmx.com>
Sun, 8 Dec 2019 20:39:54 +0000 (12:39 -0800)
committerDessalines <tyhou13@gmx.com>
Sun, 8 Dec 2019 20:39:54 +0000 (12:39 -0800)
- Fixes #360

server/src/api/community.rs
server/src/api/post.rs
server/src/api/site.rs
server/src/api/user.rs
server/src/db/comment_view.rs
server/src/db/community_view.rs
server/src/db/user_mention_view.rs
server/src/db/user_view.rs
server/src/feeds.rs

index 69113d52282db2d0805acfd0739d0a553c705485..5bd600077957051bfd12ba971c4beb027459ef5c 100644 (file)
@@ -349,9 +349,13 @@ impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
 
     let sort = SortType::from_str(&data.sort)?;
 
-    let communities: Vec<CommunityView> = CommunityView::list(
-      &conn, &sort, user_id, show_nsfw, None, data.page, data.limit,
-    )?;
+    let communities = CommunityQueryBuilder::create(&conn)
+      .sort(&sort)
+      .from_user_id_optional(user_id)
+      .show_nsfw(show_nsfw)
+      .page_optional(data.page)
+      .limit_optional(data.limit)
+      .list()?;
 
     // Return the jwt
     Ok(ListCommunitiesResponse {
index e1c9b778f92084d06b220401a60400f54bd33047..5b41b4267b9cd75ef05b200035bf5022e8c6e451 100644 (file)
@@ -178,17 +178,11 @@ impl Perform<GetPostResponse> for Oper<GetPost> {
       Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_post"))?,
     };
 
-    let comments = CommentView::list(
-      &conn,
-      &SortType::New,
-      Some(data.id),
-      None,
-      None,
-      user_id,
-      false,
-      None,
-      Some(9999),
-    )?;
+    let comments = CommentQueryBuilder::create(&conn)
+      .for_post_id(data.id)
+      .my_user_id_optional(user_id)
+      .limit(9999)
+      .list()?;
 
     let community = CommunityView::read(&conn, post_view.community_id, user_id)?;
 
index 0e780b3843265863e6b781d9b3da76d47d72bf9b..e2963d8c612740069d5d7e18e103210057edf9f4 100644 (file)
@@ -329,31 +329,28 @@ impl Perform<SearchResponse> for Oper<Search> {
           .list()?;
       }
       SearchType::Comments => {
-        comments = CommentView::list(
-          &conn,
-          &sort,
-          None,
-          None,
-          Some(data.q.to_owned()),
-          None,
-          false,
-          data.page,
-          data.limit,
-        )?;
+        comments = CommentQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
       }
       SearchType::Communities => {
-        communities = CommunityView::list(
-          &conn,
-          &sort,
-          None,
-          true,
-          Some(data.q.to_owned()),
-          data.page,
-          data.limit,
-        )?;
+        communities = CommunityQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
       }
       SearchType::Users => {
-        users = UserView::list(&conn, &sort, Some(data.q.to_owned()), data.page, data.limit)?;
+        users = UserQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
       }
       SearchType::All => {
         posts = PostQueryBuilder::create(&conn)
@@ -365,27 +362,26 @@ impl Perform<SearchResponse> for Oper<Search> {
           .limit_optional(data.limit)
           .list()?;
 
-        comments = CommentView::list(
-          &conn,
-          &sort,
-          None,
-          None,
-          Some(data.q.to_owned()),
-          None,
-          false,
-          data.page,
-          data.limit,
-        )?;
-        communities = CommunityView::list(
-          &conn,
-          &sort,
-          None,
-          true,
-          Some(data.q.to_owned()),
-          data.page,
-          data.limit,
-        )?;
-        users = UserView::list(&conn, &sort, Some(data.q.to_owned()), data.page, data.limit)?;
+        comments = CommentQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
+
+        communities = CommunityQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
+
+        users = UserQueryBuilder::create(&conn)
+          .sort(&sort)
+          .search_term(data.q.to_owned())
+          .page_optional(data.page)
+          .limit_optional(data.limit)
+          .list()?;
       }
       SearchType::Url => {
         posts = PostQueryBuilder::create(&conn)
index e3d67451b7fd2c6f3ab25613afe0948da952f707..7f7af813cfcc80ef9c8a4ac2e5081d4e8098df1a 100644 (file)
@@ -375,38 +375,22 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
       .page_optional(data.page)
       .limit_optional(data.limit);
 
+    let mut comments_query = CommentQueryBuilder::create(&conn)
+      .sort(&sort)
+      .saved_only(data.saved_only)
+      .my_user_id_optional(user_id)
+      .page_optional(data.page)
+      .limit_optional(data.limit);
+
     // If its saved only, you don't care what creator it was
+    // Or, if its not saved, then you only want it for that specific creator
     if !data.saved_only {
       posts_query = posts_query.for_creator_id(user_details_id);
+      comments_query = comments_query.for_creator_id(user_details_id);
     }
 
     let posts = posts_query.list()?;
-
-    let comments = if data.saved_only {
-      CommentView::list(
-        &conn,
-        &sort,
-        None,
-        None,
-        None,
-        Some(user_details_id),
-        data.saved_only,
-        data.page,
-        data.limit,
-      )?
-    } else {
-      CommentView::list(
-        &conn,
-        &sort,
-        None,
-        Some(user_details_id),
-        None,
-        user_id,
-        data.saved_only,
-        data.page,
-        data.limit,
-      )?
-    };
+    let comments = comments_query.list()?;
 
     let follows = CommunityFollowerView::for_user(&conn, user_details_id)?;
     let moderates = CommunityModeratorView::for_user(&conn, user_details_id)?;
@@ -569,14 +553,12 @@ impl Perform<GetRepliesResponse> for Oper<GetReplies> {
 
     let sort = SortType::from_str(&data.sort)?;
 
-    let replies = ReplyView::get_replies(
-      &conn,
-      user_id,
-      &sort,
-      data.unread_only,
-      data.page,
-      data.limit,
-    )?;
+    let replies = ReplyQueryBuilder::create(&conn, user_id)
+      .sort(&sort)
+      .unread_only(data.unread_only)
+      .page_optional(data.page)
+      .limit_optional(data.limit)
+      .list()?;
 
     Ok(GetRepliesResponse {
       op: self.op.to_string(),
@@ -599,14 +581,12 @@ impl Perform<GetUserMentionsResponse> for Oper<GetUserMentions> {
 
     let sort = SortType::from_str(&data.sort)?;
 
-    let mentions = UserMentionView::get_mentions(
-      &conn,
-      user_id,
-      &sort,
-      data.unread_only,
-      data.page,
-      data.limit,
-    )?;
+    let mentions = UserMentionQueryBuilder::create(&conn, user_id)
+      .sort(&sort)
+      .unread_only(data.unread_only)
+      .page_optional(data.page)
+      .limit_optional(data.limit)
+      .list()?;
 
     Ok(GetUserMentionsResponse {
       op: self.op.to_string(),
@@ -662,7 +642,11 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
 
     let user_id = claims.id;
 
-    let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
+    let replies = ReplyQueryBuilder::create(&conn, user_id)
+      .unread_only(true)
+      .page(1)
+      .limit(999)
+      .list()?;
 
     for reply in &replies {
       let comment_form = CommentForm {
@@ -683,8 +667,11 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
     }
 
     // Mentions
-    let mentions =
-      UserMentionView::get_mentions(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
+    let mentions = UserMentionQueryBuilder::create(&conn, user_id)
+      .unread_only(true)
+      .page(1)
+      .limit(999)
+      .list()?;
 
     for mention in &mentions {
       let mention_form = UserMentionForm {
@@ -728,17 +715,10 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
     }
 
     // Comments
-    let comments = CommentView::list(
-      &conn,
-      &SortType::New,
-      None,
-      Some(user_id),
-      None,
-      None,
-      false,
-      None,
-      Some(std::i64::MAX),
-    )?;
+    let comments = CommentQueryBuilder::create(&conn)
+      .for_creator_id(user_id)
+      .limit(std::i64::MAX)
+      .list()?;
 
     for comment in &comments {
       let comment_form = CommentForm {
index 9f75447310a98f69cae6bc8b6449b46d8dc50da5..09b864b3e876fd3fd0550f01b9f49c336ea5d73f 100644 (file)
@@ -1,4 +1,5 @@
 use super::*;
+use diesel::pg::Pg;
 
 // The faked schema since diesel doesn't do views
 table! {
@@ -53,48 +54,138 @@ pub struct CommentView {
   pub saved: Option<bool>,
 }
 
-impl CommentView {
-  pub fn list(
-    conn: &PgConnection,
-    sort: &SortType,
-    for_post_id: Option<i32>,
-    for_creator_id: Option<i32>,
-    search_term: Option<String>,
-    my_user_id: Option<i32>,
-    saved_only: bool,
-    page: Option<i64>,
-    limit: Option<i64>,
-  ) -> Result<Vec<Self>, Error> {
+pub struct CommentQueryBuilder<'a> {
+  conn: &'a PgConnection,
+  query: super::comment_view::comment_view::BoxedQuery<'a, Pg>,
+  sort: &'a SortType,
+  for_post_id: Option<i32>,
+  for_creator_id: Option<i32>,
+  search_term: Option<String>,
+  my_user_id: Option<i32>,
+  saved_only: bool,
+  page: Option<i64>,
+  limit: Option<i64>,
+}
+
+impl<'a> CommentQueryBuilder<'a> {
+  pub fn create(conn: &'a PgConnection) -> Self {
     use super::comment_view::comment_view::dsl::*;
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let query = comment_view.into_boxed();
+
+    CommentQueryBuilder {
+      conn,
+      query,
+      sort: &SortType::New,
+      for_post_id: None,
+      for_creator_id: None,
+      search_term: None,
+      my_user_id: None,
+      saved_only: false,
+      page: None,
+      limit: None,
+    }
+  }
 
-    let mut query = comment_view.into_boxed();
+  pub fn sort(mut self, sort: &'a SortType) -> Self {
+    self.sort = sort;
+    self
+  }
+
+  pub fn for_post_id(mut self, for_post_id: i32) -> Self {
+    self.for_post_id = Some(for_post_id);
+    self
+  }
+
+  pub fn for_post_id_optional(mut self, for_post_id: Option<i32>) -> Self {
+    self.for_post_id = for_post_id;
+    self
+  }
+
+  pub fn for_creator_id(mut self, for_creator_id: i32) -> Self {
+    self.for_creator_id = Some(for_creator_id);
+    self
+  }
+
+  pub fn for_creator_id_optional(mut self, for_creator_id: Option<i32>) -> Self {
+    self.for_creator_id = for_creator_id;
+    self
+  }
+
+  pub fn search_term(mut self, search_term: String) -> Self {
+    self.search_term = Some(search_term);
+    self
+  }
+
+  pub fn search_term_optional(mut self, search_term: Option<String>) -> Self {
+    self.search_term = search_term;
+    self
+  }
+
+  pub fn my_user_id(mut self, my_user_id: i32) -> Self {
+    self.my_user_id = Some(my_user_id);
+    self
+  }
+
+  pub fn my_user_id_optional(mut self, my_user_id: Option<i32>) -> Self {
+    self.my_user_id = my_user_id;
+    self
+  }
+
+  pub fn saved_only(mut self, saved_only: bool) -> Self {
+    self.saved_only = saved_only;
+    self
+  }
+
+  pub fn page(mut self, page: i64) -> Self {
+    self.page = Some(page);
+    self
+  }
+
+  pub fn page_optional(mut self, page: Option<i64>) -> Self {
+    self.page = page;
+    self
+  }
+
+  pub fn limit(mut self, limit: i64) -> Self {
+    self.limit = Some(limit);
+    self
+  }
+
+  pub fn limit_optional(mut self, limit: Option<i64>) -> Self {
+    self.limit = limit;
+    self
+  }
+
+  pub fn list(self) -> Result<Vec<CommentView>, Error> {
+    use super::comment_view::comment_view::dsl::*;
+
+    let mut query = self.query;
 
     // The view lets you pass a null user_id, if you're not logged in
-    if let Some(my_user_id) = my_user_id {
+    if let Some(my_user_id) = self.my_user_id {
       query = query.filter(user_id.eq(my_user_id));
     } else {
       query = query.filter(user_id.is_null());
     }
 
-    if let Some(for_creator_id) = for_creator_id {
+    if let Some(for_creator_id) = self.for_creator_id {
       query = query.filter(creator_id.eq(for_creator_id));
     };
 
-    if let Some(for_post_id) = for_post_id {
+    if let Some(for_post_id) = self.for_post_id {
       query = query.filter(post_id.eq(for_post_id));
     };
 
-    if let Some(search_term) = search_term {
+    if let Some(search_term) = self.search_term {
       query = query.filter(content.ilike(fuzzy_search(&search_term)));
     };
 
-    if saved_only {
+    if self.saved_only {
       query = query.filter(saved.eq(true));
     }
 
-    query = match sort {
+    query = match self.sort {
       // SortType::Hot => query.order(hot_rank.desc(), published.desc()),
       SortType::New => query.order_by(published.desc()),
       SortType::TopAll => query.order_by(score.desc()),
@@ -113,10 +204,17 @@ impl CommentView {
       _ => query.order_by(published.desc()),
     };
 
+    let (limit, offset) = limit_and_offset(self.page, self.limit);
+
     // Note: deleted and removed comments are done on the front side
-    query.limit(limit).offset(offset).load::<Self>(conn)
+    query
+      .limit(limit)
+      .offset(offset)
+      .load::<CommentView>(self.conn)
   }
+}
 
+impl CommentView {
   pub fn read(
     conn: &PgConnection,
     from_comment_id: i32,
@@ -196,30 +294,77 @@ pub struct ReplyView {
   pub recipient_id: i32,
 }
 
-impl ReplyView {
-  pub fn get_replies(
-    conn: &PgConnection,
-    for_user_id: i32,
-    sort: &SortType,
-    unread_only: bool,
-    page: Option<i64>,
-    limit: Option<i64>,
-  ) -> Result<Vec<Self>, Error> {
+pub struct ReplyQueryBuilder<'a> {
+  conn: &'a PgConnection,
+  query: super::comment_view::reply_view::BoxedQuery<'a, Pg>,
+  for_user_id: i32,
+  sort: &'a SortType,
+  unread_only: bool,
+  page: Option<i64>,
+  limit: Option<i64>,
+}
+
+impl<'a> ReplyQueryBuilder<'a> {
+  pub fn create(conn: &'a PgConnection, for_user_id: i32) -> Self {
     use super::comment_view::reply_view::dsl::*;
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let query = reply_view.into_boxed();
 
-    let mut query = reply_view.into_boxed();
+    ReplyQueryBuilder {
+      conn,
+      query,
+      for_user_id: for_user_id,
+      sort: &SortType::New,
+      unread_only: false,
+      page: None,
+      limit: None,
+    }
+  }
+
+  pub fn sort(mut self, sort: &'a SortType) -> Self {
+    self.sort = sort;
+    self
+  }
+
+  pub fn unread_only(mut self, unread_only: bool) -> Self {
+    self.unread_only = unread_only;
+    self
+  }
+
+  pub fn page(mut self, page: i64) -> Self {
+    self.page = Some(page);
+    self
+  }
+
+  pub fn page_optional(mut self, page: Option<i64>) -> Self {
+    self.page = page;
+    self
+  }
+
+  pub fn limit(mut self, limit: i64) -> Self {
+    self.limit = Some(limit);
+    self
+  }
+
+  pub fn limit_optional(mut self, limit: Option<i64>) -> Self {
+    self.limit = limit;
+    self
+  }
+
+  pub fn list(self) -> Result<Vec<ReplyView>, Error> {
+    use super::comment_view::reply_view::dsl::*;
+
+    let mut query = self.query;
 
     query = query
-      .filter(user_id.eq(for_user_id))
-      .filter(recipient_id.eq(for_user_id));
+      .filter(user_id.eq(self.for_user_id))
+      .filter(recipient_id.eq(self.for_user_id));
 
-    if unread_only {
+    if self.unread_only {
       query = query.filter(read.eq(false));
     }
 
-    query = match sort {
+    query = match self.sort {
       // SortType::Hot => query.order_by(hot_rank.desc()),
       SortType::New => query.order_by(published.desc()),
       SortType::TopAll => query.order_by(score.desc()),
@@ -238,7 +383,11 @@ impl ReplyView {
       _ => query.order_by(published.desc()),
     };
 
-    query.limit(limit).offset(offset).load::<Self>(conn)
+    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    query
+      .limit(limit)
+      .offset(offset)
+      .load::<ReplyView>(self.conn)
   }
 }
 
@@ -368,30 +517,16 @@ mod tests {
       saved: None,
     };
 
-    let read_comment_views_no_user = CommentView::list(
-      &conn,
-      &SortType::New,
-      Some(inserted_post.id),
-      None,
-      None,
-      None,
-      false,
-      None,
-      None,
-    )
-    .unwrap();
-    let read_comment_views_with_user = CommentView::list(
-      &conn,
-      &SortType::New,
-      Some(inserted_post.id),
-      None,
-      None,
-      Some(inserted_user.id),
-      false,
-      None,
-      None,
-    )
-    .unwrap();
+    let read_comment_views_no_user = CommentQueryBuilder::create(&conn)
+      .for_post_id(inserted_post.id)
+      .list()
+      .unwrap();
+    let read_comment_views_with_user = CommentQueryBuilder::create(&conn)
+      .for_post_id(inserted_post.id)
+      .for_creator_id(inserted_user.id)
+      .list()
+      .unwrap();
+
     let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
     let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
     Post::delete(&conn, inserted_post.id).unwrap();
index dabf01bcbf14b6d51236d966b33f6e270a32717d..c90beaba5ada0b3ea68ee94062a113c6a933568d 100644 (file)
@@ -1,4 +1,6 @@
+use super::community_view::community_view::BoxedQuery;
 use super::*;
+use diesel::pg::Pg;
 
 table! {
   community_view (id) {
@@ -99,48 +101,98 @@ pub struct CommunityView {
   pub subscribed: Option<bool>,
 }
 
-impl CommunityView {
-  pub fn read(
-    conn: &PgConnection,
-    from_community_id: i32,
-    from_user_id: Option<i32>,
-  ) -> Result<Self, Error> {
+pub struct CommunityQueryBuilder<'a> {
+  conn: &'a PgConnection,
+  query: BoxedQuery<'a, Pg>,
+  sort: &'a SortType,
+  from_user_id: Option<i32>,
+  show_nsfw: bool,
+  search_term: Option<String>,
+  page: Option<i64>,
+  limit: Option<i64>,
+}
+
+impl<'a> CommunityQueryBuilder<'a> {
+  pub fn create(conn: &'a PgConnection) -> Self {
     use super::community_view::community_view::dsl::*;
 
-    let mut query = community_view.into_boxed();
+    let query = community_view.into_boxed();
 
-    query = query.filter(id.eq(from_community_id));
+    CommunityQueryBuilder {
+      conn,
+      query,
+      sort: &SortType::Hot,
+      from_user_id: None,
+      show_nsfw: true,
+      search_term: None,
+      page: None,
+      limit: None,
+    }
+  }
 
-    // The view lets you pass a null user_id, if you're not logged in
-    if let Some(from_user_id) = from_user_id {
-      query = query.filter(user_id.eq(from_user_id));
-    } else {
-      query = query.filter(user_id.is_null());
-    };
+  pub fn sort(mut self, sort: &'a SortType) -> Self {
+    self.sort = sort;
+    self
+  }
 
-    query.first::<Self>(conn)
+  pub fn from_user_id(mut self, from_user_id: i32) -> Self {
+    self.from_user_id = Some(from_user_id);
+    self
   }
 
-  pub fn list(
-    conn: &PgConnection,
-    sort: &SortType,
-    from_user_id: Option<i32>,
-    show_nsfw: bool,
-    search_term: Option<String>,
-    page: Option<i64>,
-    limit: Option<i64>,
-  ) -> Result<Vec<Self>, Error> {
+  pub fn from_user_id_optional(self, from_user_id: Option<i32>) -> Self {
+    match from_user_id {
+      Some(from_user_id) => self.from_user_id(from_user_id),
+      None => self,
+    }
+  }
+
+  pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
+    self.show_nsfw = show_nsfw;
+    self
+  }
+
+  pub fn search_term(mut self, search_term: String) -> Self {
+    self.search_term = Some(search_term);
+    self
+  }
+
+  pub fn search_term_optional(mut self, search_term: Option<String>) -> Self {
+    self.search_term = search_term;
+    self
+  }
+
+  pub fn page(mut self, page: i64) -> Self {
+    self.page = Some(page);
+    self
+  }
+
+  pub fn page_optional(mut self, page: Option<i64>) -> Self {
+    self.page = page;
+    self
+  }
+
+  pub fn limit(mut self, limit: i64) -> Self {
+    self.limit = Some(limit);
+    self
+  }
+
+  pub fn limit_optional(mut self, limit: Option<i64>) -> Self {
+    self.limit = limit;
+    self
+  }
+
+  pub fn list(self) -> Result<Vec<CommunityView>, Error> {
     use super::community_view::community_view::dsl::*;
-    let mut query = community_view.into_boxed();
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let mut query = self.query;
 
-    if let Some(search_term) = search_term {
+    if let Some(search_term) = self.search_term {
       query = query.filter(name.ilike(fuzzy_search(&search_term)));
     };
 
     // The view lets you pass a null user_id, if you're not logged in
-    match sort {
+    match self.sort {
       SortType::Hot => {
         query = query
           .order_by(hot_rank.desc())
@@ -148,7 +200,7 @@ impl CommunityView {
           .filter(user_id.is_null())
       }
       SortType::New => query = query.order_by(published.desc()).filter(user_id.is_null()),
-      SortType::TopAll => match from_user_id {
+      SortType::TopAll => match self.from_user_id {
         Some(from_user_id) => {
           query = query
             .filter(user_id.eq(from_user_id))
@@ -163,16 +215,40 @@ impl CommunityView {
       _ => (),
     };
 
-    if !show_nsfw {
+    if !self.show_nsfw {
       query = query.filter(nsfw.eq(false));
     };
 
+    let (limit, offset) = limit_and_offset(self.page, self.limit);
     query
       .limit(limit)
       .offset(offset)
       .filter(removed.eq(false))
       .filter(deleted.eq(false))
-      .load::<Self>(conn)
+      .load::<CommunityView>(self.conn)
+  }
+}
+
+impl CommunityView {
+  pub fn read(
+    conn: &PgConnection,
+    from_community_id: i32,
+    from_user_id: Option<i32>,
+  ) -> Result<Self, Error> {
+    use super::community_view::community_view::dsl::*;
+
+    let mut query = community_view.into_boxed();
+
+    query = query.filter(id.eq(from_community_id));
+
+    // The view lets you pass a null user_id, if you're not logged in
+    if let Some(from_user_id) = from_user_id {
+      query = query.filter(user_id.eq(from_user_id));
+    } else {
+      query = query.filter(user_id.is_null());
+    };
+
+    query.first::<Self>(conn)
   }
 }
 
index 6676ab9ab4f4fab25aaf0541d949f80eb7e22217..19b803da8966c7755dba10f1862d16246226d9b7 100644 (file)
@@ -1,4 +1,6 @@
+use super::user_mention_view::user_mention_view::BoxedQuery;
 use super::*;
+use diesel::pg::Pg;
 
 // The faked schema since diesel doesn't do views
 table! {
@@ -57,30 +59,77 @@ pub struct UserMentionView {
   pub recipient_id: i32,
 }
 
-impl UserMentionView {
-  pub fn get_mentions(
-    conn: &PgConnection,
-    for_user_id: i32,
-    sort: &SortType,
-    unread_only: bool,
-    page: Option<i64>,
-    limit: Option<i64>,
-  ) -> Result<Vec<Self>, Error> {
+pub struct UserMentionQueryBuilder<'a> {
+  conn: &'a PgConnection,
+  query: BoxedQuery<'a, Pg>,
+  for_user_id: i32,
+  sort: &'a SortType,
+  unread_only: bool,
+  page: Option<i64>,
+  limit: Option<i64>,
+}
+
+impl<'a> UserMentionQueryBuilder<'a> {
+  pub fn create(conn: &'a PgConnection, for_user_id: i32) -> Self {
     use super::user_mention_view::user_mention_view::dsl::*;
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let query = user_mention_view.into_boxed();
 
-    let mut query = user_mention_view.into_boxed();
+    UserMentionQueryBuilder {
+      conn,
+      query,
+      for_user_id: for_user_id,
+      sort: &SortType::New,
+      unread_only: false,
+      page: None,
+      limit: None,
+    }
+  }
 
-    query = query
-      .filter(user_id.eq(for_user_id))
-      .filter(recipient_id.eq(for_user_id));
+  pub fn sort(mut self, sort: &'a SortType) -> Self {
+    self.sort = sort;
+    self
+  }
+
+  pub fn unread_only(mut self, unread_only: bool) -> Self {
+    self.unread_only = unread_only;
+    self
+  }
 
-    if unread_only {
+  pub fn page(mut self, page: i64) -> Self {
+    self.page = Some(page);
+    self
+  }
+
+  pub fn page_optional(mut self, page: Option<i64>) -> Self {
+    self.page = page;
+    self
+  }
+
+  pub fn limit(mut self, limit: i64) -> Self {
+    self.limit = Some(limit);
+    self
+  }
+
+  pub fn limit_optional(mut self, limit: Option<i64>) -> Self {
+    self.limit = limit;
+    self
+  }
+
+  pub fn list(self) -> Result<Vec<UserMentionView>, Error> {
+    use super::user_mention_view::user_mention_view::dsl::*;
+
+    let mut query = self.query;
+
+    if self.unread_only {
       query = query.filter(read.eq(false));
     }
 
-    query = match sort {
+    query = query
+      .filter(user_id.eq(self.for_user_id))
+      .filter(recipient_id.eq(self.for_user_id));
+
+    query = match self.sort {
       // SortType::Hot => query.order_by(hot_rank.desc()),
       SortType::New => query.order_by(published.desc()),
       SortType::TopAll => query.order_by(score.desc()),
@@ -99,9 +148,15 @@ impl UserMentionView {
       _ => query.order_by(published.desc()),
     };
 
-    query.limit(limit).offset(offset).load::<Self>(conn)
+    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    query
+      .limit(limit)
+      .offset(offset)
+      .load::<UserMentionView>(self.conn)
   }
+}
 
+impl UserMentionView {
   pub fn read(
     conn: &PgConnection,
     from_user_mention_id: i32,
index 028cd07c14118773989a473167b9edbe2feb9a6a..0637d647ee8342b8de48f760412913f1216fa4a6 100644 (file)
@@ -1,4 +1,6 @@
+use super::user_view::user_view::BoxedQuery;
 use super::*;
+use diesel::pg::Pg;
 
 table! {
   user_view (id) {
@@ -32,25 +34,73 @@ pub struct UserView {
   pub comment_score: i64,
 }
 
-impl UserView {
-  pub fn list(
-    conn: &PgConnection,
-    sort: &SortType,
-    search_term: Option<String>,
-    page: Option<i64>,
-    limit: Option<i64>,
-  ) -> Result<Vec<Self>, Error> {
+pub struct UserQueryBuilder<'a> {
+  conn: &'a PgConnection,
+  query: BoxedQuery<'a, Pg>,
+  sort: &'a SortType,
+  page: Option<i64>,
+  limit: Option<i64>,
+}
+
+impl<'a> UserQueryBuilder<'a> {
+  pub fn create(conn: &'a PgConnection) -> Self {
     use super::user_view::user_view::dsl::*;
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let query = user_view.into_boxed();
 
-    let mut query = user_view.into_boxed();
+    UserQueryBuilder {
+      conn,
+      query,
+      sort: &SortType::Hot,
+      page: None,
+      limit: None,
+    }
+  }
 
-    if let Some(search_term) = search_term {
-      query = query.filter(name.ilike(fuzzy_search(&search_term)));
-    };
+  pub fn sort(mut self, sort: &'a SortType) -> Self {
+    self.sort = sort;
+    self
+  }
+
+  pub fn search_term(mut self, search_term: String) -> Self {
+    use super::user_view::user_view::dsl::*;
+    self.query = self.query.filter(name.ilike(fuzzy_search(&search_term)));
+    self
+  }
+
+  pub fn search_term_optional(self, search_term: Option<String>) -> Self {
+    match search_term {
+      Some(search_term) => self.search_term(search_term),
+      None => self,
+    }
+  }
+
+  pub fn page(mut self, page: i64) -> Self {
+    self.page = Some(page);
+    self
+  }
+
+  pub fn page_optional(mut self, page: Option<i64>) -> Self {
+    self.page = page;
+    self
+  }
+
+  pub fn limit(mut self, limit: i64) -> Self {
+    self.limit = Some(limit);
+    self
+  }
+
+  pub fn limit_optional(mut self, limit: Option<i64>) -> Self {
+    self.limit = limit;
+    self
+  }
+
+  pub fn list(self) -> Result<Vec<UserView>, Error> {
+    use super::user_view::user_view::dsl::*;
 
-    query = match sort {
+    let mut query = self.query;
+
+    query = match self.sort {
       SortType::Hot => query
         .order_by(comment_score.desc())
         .then_order_by(published.desc()),
@@ -70,11 +120,14 @@ impl UserView {
         .order_by(comment_score.desc()),
     };
 
+    let (limit, offset) = limit_and_offset(self.page, self.limit);
     query = query.limit(limit).offset(offset);
 
-    query.load::<Self>(conn)
+    query.load::<UserView>(self.conn)
   }
+}
 
+impl UserView {
   pub fn read(conn: &PgConnection, from_user_id: i32) -> Result<Self, Error> {
     use super::user_view::user_view::dsl::*;
 
index 82ad3526f418486103cdf936f4141dc7e5bd1922..810f6d5967991cbeed1807a92118f4fba23d8ffa 100644 (file)
@@ -1,12 +1,12 @@
 extern crate rss;
 
 use super::*;
-use crate::db::comment_view::ReplyView;
+use crate::db::comment_view::{ReplyQueryBuilder, ReplyView};
 use crate::db::community::Community;
 use crate::db::community_view::SiteView;
 use crate::db::post_view::{PostQueryBuilder, PostView};
 use crate::db::user::User_;
-use crate::db::user_mention_view::UserMentionView;
+use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView};
 use crate::db::{establish_connection, ListingType, SortType};
 use crate::Settings;
 use actix_web::body::Body;
@@ -193,9 +193,13 @@ fn get_feed_inbox(jwt: String) -> Result<String, Error> {
 
   let sort = SortType::New;
 
-  let replies = ReplyView::get_replies(&conn, user_id, &sort, false, None, None)?;
+  let replies = ReplyQueryBuilder::create(&conn, user_id)
+    .sort(&sort)
+    .list()?;
 
-  let mentions = UserMentionView::get_mentions(&conn, user_id, &sort, false, None, None)?;
+  let mentions = UserMentionQueryBuilder::create(&conn, user_id)
+    .sort(&sort)
+    .list()?;
 
   let items = create_reply_and_mention_items(replies, mentions);