]> Untitled Git - lemmy.git/blob - crates/db_queries/src/aggregates/post_aggregates.rs
Add both (De)Serialize to all models (#1851)
[lemmy.git] / crates / db_queries / src / aggregates / post_aggregates.rs
1 use diesel::{result::Error, *};
2 use lemmy_db_schema::{schema::post_aggregates, PostId};
3 use serde::{Deserialize, Serialize};
4
5 #[derive(
6   Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Deserialize, Clone,
7 )]
8 #[table_name = "post_aggregates"]
9 pub struct PostAggregates {
10   pub id: i32,
11   pub post_id: PostId,
12   pub comments: i64,
13   pub score: i64,
14   pub upvotes: i64,
15   pub downvotes: i64,
16   pub stickied: bool,
17   pub published: chrono::NaiveDateTime,
18   pub newest_comment_time_necro: chrono::NaiveDateTime, // A newest comment time, limited to 2 days, to prevent necrobumping
19   pub newest_comment_time: chrono::NaiveDateTime,
20 }
21
22 impl PostAggregates {
23   pub fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
24     post_aggregates::table
25       .filter(post_aggregates::post_id.eq(post_id))
26       .first::<Self>(conn)
27   }
28 }
29
30 #[cfg(test)]
31 mod tests {
32   use crate::{
33     aggregates::post_aggregates::PostAggregates,
34     establish_unpooled_connection,
35     Crud,
36     Likeable,
37   };
38   use lemmy_db_schema::source::{
39     comment::{Comment, CommentForm},
40     community::{Community, CommunityForm},
41     person::{Person, PersonForm},
42     post::{Post, PostForm, PostLike, PostLikeForm},
43   };
44   use serial_test::serial;
45
46   #[test]
47   #[serial]
48   fn test_crud() {
49     let conn = establish_unpooled_connection();
50
51     let new_person = PersonForm {
52       name: "thommy_community_agg".into(),
53       ..PersonForm::default()
54     };
55
56     let inserted_person = Person::create(&conn, &new_person).unwrap();
57
58     let another_person = PersonForm {
59       name: "jerry_community_agg".into(),
60       ..PersonForm::default()
61     };
62
63     let another_inserted_person = Person::create(&conn, &another_person).unwrap();
64
65     let new_community = CommunityForm {
66       name: "TIL_community_agg".into(),
67       title: "nada".to_owned(),
68       ..CommunityForm::default()
69     };
70
71     let inserted_community = Community::create(&conn, &new_community).unwrap();
72
73     let new_post = PostForm {
74       name: "A test post".into(),
75       creator_id: inserted_person.id,
76       community_id: inserted_community.id,
77       ..PostForm::default()
78     };
79
80     let inserted_post = Post::create(&conn, &new_post).unwrap();
81
82     let comment_form = CommentForm {
83       content: "A test comment".into(),
84       creator_id: inserted_person.id,
85       post_id: inserted_post.id,
86       ..CommentForm::default()
87     };
88
89     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
90
91     let child_comment_form = CommentForm {
92       content: "A test comment".into(),
93       creator_id: inserted_person.id,
94       post_id: inserted_post.id,
95       parent_id: Some(inserted_comment.id),
96       ..CommentForm::default()
97     };
98
99     let _inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
100
101     let post_like = PostLikeForm {
102       post_id: inserted_post.id,
103       person_id: inserted_person.id,
104       score: 1,
105     };
106
107     PostLike::like(&conn, &post_like).unwrap();
108
109     let post_aggs_before_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
110
111     assert_eq!(2, post_aggs_before_delete.comments);
112     assert_eq!(1, post_aggs_before_delete.score);
113     assert_eq!(1, post_aggs_before_delete.upvotes);
114     assert_eq!(0, post_aggs_before_delete.downvotes);
115
116     // Add a post dislike from the other person
117     let post_dislike = PostLikeForm {
118       post_id: inserted_post.id,
119       person_id: another_inserted_person.id,
120       score: -1,
121     };
122
123     PostLike::like(&conn, &post_dislike).unwrap();
124
125     let post_aggs_after_dislike = PostAggregates::read(&conn, inserted_post.id).unwrap();
126
127     assert_eq!(2, post_aggs_after_dislike.comments);
128     assert_eq!(0, post_aggs_after_dislike.score);
129     assert_eq!(1, post_aggs_after_dislike.upvotes);
130     assert_eq!(1, post_aggs_after_dislike.downvotes);
131
132     // Remove the parent comment
133     Comment::delete(&conn, inserted_comment.id).unwrap();
134     let after_comment_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
135     assert_eq!(0, after_comment_delete.comments);
136     assert_eq!(0, after_comment_delete.score);
137     assert_eq!(1, after_comment_delete.upvotes);
138     assert_eq!(1, after_comment_delete.downvotes);
139
140     // Remove the first post like
141     PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
142     let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
143     assert_eq!(0, after_like_remove.comments);
144     assert_eq!(-1, after_like_remove.score);
145     assert_eq!(0, after_like_remove.upvotes);
146     assert_eq!(1, after_like_remove.downvotes);
147
148     // This should delete all the associated rows, and fire triggers
149     Person::delete(&conn, another_inserted_person.id).unwrap();
150     let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
151     assert_eq!(1, person_num_deleted);
152
153     // Delete the community
154     let community_num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
155     assert_eq!(1, community_num_deleted);
156
157     // Should be none found, since the creator was deleted
158     let after_delete = PostAggregates::read(&conn, inserted_post.id);
159     assert!(after_delete.is_err());
160   }
161 }