Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 56d2ff7

Browse files
committed
refactor(article-comment): wip
1 parent 76bad31 commit 56d2ff7

File tree

8 files changed

+204
-90
lines changed

8 files changed

+204
-90
lines changed

lib/groupher_server/cms/article_comment_user_emotion.ex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,13 @@ defmodule GroupherServer.CMS.ArticleCommentUserEmotion do
5050
|> foreign_key_constraint(:user_id)
5151
|> foreign_key_constraint(:recived_user_id)
5252
end
53+
54+
def update_changeset(%ArticleCommentUserEmotion{} = struct, attrs) do
55+
struct
56+
|> cast(attrs, @required_fields ++ @optional_fields)
57+
|> validate_required(@required_fields)
58+
|> foreign_key_constraint(:article_comment_id)
59+
|> foreign_key_constraint(:user_id)
60+
|> foreign_key_constraint(:recived_user_id)
61+
end
5362
end

lib/groupher_server/cms/cms.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ defmodule GroupherServer.CMS do
1313
ArticleOperation,
1414
ArticleReaction,
1515
ArticleComment,
16+
ArticleCommentEmotion,
1617
CommentCURD,
1718
CommunitySync,
18-
CommentReaction,
1919
CommunityCURD,
2020
CommunityOperation,
2121
PassportCURD,
@@ -136,7 +136,8 @@ defmodule GroupherServer.CMS do
136136
defdelegate pin_article_comment(comment_id), to: ArticleComment
137137
defdelegate undo_pin_article_comment(comment_id), to: ArticleComment
138138

139-
defdelegate emotion_to_comment(comment_id, args, user), to: ArticleComment
139+
defdelegate emotion_to_comment(comment_id, args, user), to: ArticleCommentEmotion
140+
defdelegate undo_emotion_to_comment(comment_id, args, user), to: ArticleCommentEmotion
140141
defdelegate fold_article_comment(comment_id, user), to: ArticleComment
141142
defdelegate unfold_article_comment(comment_id, user), to: ArticleComment
142143
defdelegate report_article_comment(comment_id, user), to: ArticleComment

lib/groupher_server/cms/delegates/article_comment.ex

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
2020
ArticlePinedComment,
2121
ArticleCommentUpvote,
2222
ArticleCommentReply,
23-
ArticleCommentUserEmotion,
2423
Embeds,
2524
Post,
2625
Job
2726
}
2827

2928
alias Ecto.Multi
3029

31-
@max_latest_emotion_users_count ArticleComment.max_latest_emotion_users_count()
3230
@max_participator_count ArticleComment.max_participator_count()
3331
@max_parent_replies_count ArticleComment.max_parent_replies_count()
3432
@default_emotions Embeds.ArticleCommentEmotion.default_emotions()
@@ -206,79 +204,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
206204
end
207205
end
208206

209-
@doc "make emotion to a comment"
210-
def emotion_to_comment(comment_id, emotion, %User{} = user) do
211-
with {:ok, comment} <-
212-
ORM.find(ArticleComment, comment_id) do
213-
Multi.new()
214-
|> Multi.run(:create_user_emotion, fn _, _ ->
215-
args =
216-
Map.put(
217-
%{
218-
article_comment_id: comment.id,
219-
recived_user_id: comment.author_id,
220-
user_id: user.id
221-
},
222-
:"#{emotion}",
223-
true
224-
)
225-
226-
{:ok, _} = ArticleCommentUserEmotion |> ORM.create(args)
227-
end)
228-
|> Multi.run(:query_emotion_status, fn _, _ ->
229-
# 每次被 emotion 动作触发后重新查询,主要原因
230-
# 1.并发下保证数据准确,类似 views 阅读数的统计
231-
# 2. 前端使用 nickname 而非 login 展示,如果用户改了 nickname, 可以"自动纠正"
232-
query =
233-
from(a in ArticleCommentUserEmotion,
234-
join: user in User,
235-
on: a.user_id == user.id,
236-
where: a.article_comment_id == ^comment.id,
237-
where: field(a, ^emotion) == true,
238-
select: %{login: user.login, nickname: user.nickname}
239-
)
240-
241-
emotioned_user_info_list = Repo.all(query) |> Enum.uniq()
242-
emotioned_user_count = length(emotioned_user_info_list)
243-
244-
{:ok, %{user_list: emotioned_user_info_list, user_count: emotioned_user_count}}
245-
end)
246-
|> Multi.run(:update_comment_emotion, fn _, %{query_emotion_status: status} ->
247-
%{user_count: user_count, user_list: user_list} = status
248-
249-
updated_emotions =
250-
%{}
251-
|> Map.put(:"#{emotion}_count", user_count)
252-
|> Map.put(:"#{emotion}_user_logins", user_list |> Enum.map(& &1.login))
253-
|> Map.put(
254-
:"latest_#{emotion}_users",
255-
Enum.slice(user_list, 0, @max_latest_emotion_users_count)
256-
)
257-
258-
viewer_has_emotioned = user.login in Map.get(updated_emotions, :"#{emotion}_user_logins")
259-
260-
updated_emotions =
261-
updated_emotions |> Map.put(:"viewer_has_#{emotion}ed", viewer_has_emotioned)
262-
263-
comment
264-
|> Ecto.Changeset.change()
265-
|> Ecto.Changeset.put_embed(:emotions, updated_emotions)
266-
|> Repo.update()
267-
# virtual field can not be updated
268-
|> add_viewer_emotioned_ifneed(updated_emotions)
269-
end)
270-
|> Repo.transaction()
271-
|> upsert_comment_result
272-
end
273-
end
274-
275-
defp add_viewer_emotioned_ifneed({:error, error}, _), do: {:error, error}
276-
277-
defp add_viewer_emotioned_ifneed({:ok, comment}, emotions) do
278-
# Map.merge(comment, %{emotion: emotions})
279-
{:ok, Map.merge(comment, %{emotion: emotions})}
280-
end
281-
282207
@doc """
283208
creates a comment for article like psot, job ...
284209
"""
@@ -722,7 +647,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
722647
defp upsert_comment_result({:ok, %{add_reply_to: result}}), do: {:ok, result}
723648
defp upsert_comment_result({:ok, %{check_article_author_upvoted: result}}), do: {:ok, result}
724649
defp upsert_comment_result({:ok, %{update_report_flag: result}}), do: {:ok, result}
725-
defp upsert_comment_result({:ok, %{update_comment_emotion: result}}), do: {:ok, result}
726650
defp upsert_comment_result({:ok, %{update_comment_flag: result}}), do: {:ok, result}
727651
defp upsert_comment_result({:ok, %{delete_article_comment: result}}), do: {:ok, result}
728652

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
defmodule GroupherServer.CMS.Delegate.ArticleCommentEmotion do
2+
@moduledoc """
3+
CURD and operations for article comments
4+
"""
5+
import Ecto.Query, warn: false
6+
7+
# alias Helper.Types, as: T
8+
alias Helper.ORM
9+
alias GroupherServer.{Accounts, CMS, Repo}
10+
11+
alias Accounts.User
12+
alias CMS.{ArticleComment, ArticleCommentUserEmotion}
13+
14+
alias Ecto.Multi
15+
16+
@max_latest_emotion_users_count ArticleComment.max_latest_emotion_users_count()
17+
18+
@doc "make emotion to a comment"
19+
def emotion_to_comment(comment_id, emotion, %User{} = user) do
20+
with {:ok, comment} <- ORM.find(ArticleComment, comment_id, preload: :author) do
21+
Multi.new()
22+
|> Multi.run(:create_user_emotion, fn _, _ ->
23+
# dTODO:
24+
# 分两步
25+
# 当前如果有记录,那么直接 emotion 相应置位 boolean 就好
26+
# 如果没有找到记录,那么才就要创建
27+
target = %{
28+
article_comment_id: comment.id,
29+
recived_user_id: comment.author.id,
30+
user_id: user.id
31+
}
32+
33+
args = Map.put(target, :"#{emotion}", true)
34+
35+
ArticleCommentUserEmotion |> ORM.create(args)
36+
end)
37+
|> Multi.run(:query_emotion_status, fn _, _ ->
38+
# 每次被 emotion 动作触发后重新查询,主要原因
39+
# 1.并发下保证数据准确,类似 views 阅读数的统计
40+
# 2. 前端使用 nickname 而非 login 展示,如果用户改了 nickname, 可以"自动纠正"
41+
query =
42+
from(a in ArticleCommentUserEmotion,
43+
join: user in User,
44+
on: a.user_id == user.id,
45+
where: a.article_comment_id == ^comment.id,
46+
where: field(a, ^emotion) == true,
47+
select: %{login: user.login, nickname: user.nickname}
48+
)
49+
50+
emotioned_user_info_list = Repo.all(query) |> Enum.uniq()
51+
emotioned_user_count = length(emotioned_user_info_list)
52+
53+
{:ok, %{user_list: emotioned_user_info_list, user_count: emotioned_user_count}}
54+
end)
55+
|> Multi.run(:update_comment_emotion, fn _, %{query_emotion_status: status} ->
56+
%{user_count: user_count, user_list: user_list} = status
57+
58+
updated_emotions =
59+
%{}
60+
|> Map.put(:"#{emotion}_count", user_count)
61+
|> Map.put(:"#{emotion}_user_logins", user_list |> Enum.map(& &1.login))
62+
|> Map.put(
63+
:"latest_#{emotion}_users",
64+
Enum.slice(user_list, 0, @max_latest_emotion_users_count)
65+
)
66+
67+
viewer_has_emotioned = user.login in Map.get(updated_emotions, :"#{emotion}_user_logins")
68+
69+
updated_emotions =
70+
updated_emotions |> Map.put(:"viewer_has_#{emotion}ed", viewer_has_emotioned)
71+
72+
comment
73+
|> Ecto.Changeset.change()
74+
|> Ecto.Changeset.put_embed(:emotions, updated_emotions)
75+
|> Repo.update()
76+
# virtual field can not be updated
77+
|> add_viewer_emotioned_ifneed(updated_emotions)
78+
end)
79+
|> Repo.transaction()
80+
|> upsert_comment_result
81+
end
82+
end
83+
84+
def undo_emotion_to_comment(comment_id, emotion, %User{} = user) do
85+
with {:ok, comment} <- ORM.find(ArticleComment, comment_id, preload: :author) do
86+
Multi.new()
87+
|> Multi.run(:update_user_emotion, fn _, _ ->
88+
target = %{
89+
article_comment_id: comment.id,
90+
recived_user_id: comment.author.id,
91+
user_id: user.id
92+
}
93+
94+
{:ok, article_comment_user_emotion} = ORM.find_by(ArticleCommentUserEmotion, target)
95+
args = Map.put(target, :"#{emotion}", false)
96+
article_comment_user_emotion |> ORM.update(args)
97+
end)
98+
|> Multi.run(:query_emotion_status, fn _, _ ->
99+
# 每次被 emotion 动作触发后重新查询,主要原因
100+
# 1.并发下保证数据准确,类似 views 阅读数的统计
101+
# 2. 前端使用 nickname 而非 login 展示,如果用户改了 nickname, 可以"自动纠正"
102+
query =
103+
from(a in ArticleCommentUserEmotion,
104+
join: user in User,
105+
on: a.user_id == user.id,
106+
where: a.article_comment_id == ^comment.id,
107+
where: field(a, ^emotion) == true,
108+
select: %{login: user.login, nickname: user.nickname}
109+
)
110+
111+
emotioned_user_info_list = Repo.all(query) |> Enum.uniq()
112+
emotioned_user_count = length(emotioned_user_info_list)
113+
114+
{:ok, %{user_list: emotioned_user_info_list, user_count: emotioned_user_count}}
115+
end)
116+
|> Multi.run(:update_comment_emotion, fn _, %{query_emotion_status: status} ->
117+
%{user_count: user_count, user_list: user_list} = status
118+
119+
updated_emotions =
120+
%{}
121+
|> Map.put(:"#{emotion}_count", user_count)
122+
|> Map.put(:"#{emotion}_user_logins", user_list |> Enum.map(& &1.login))
123+
|> Map.put(
124+
:"latest_#{emotion}_users",
125+
Enum.slice(user_list, 0, @max_latest_emotion_users_count)
126+
)
127+
128+
viewer_has_emotioned = user.login in Map.get(updated_emotions, :"#{emotion}_user_logins")
129+
130+
updated_emotions =
131+
updated_emotions |> Map.put(:"viewer_has_#{emotion}ed", viewer_has_emotioned)
132+
133+
comment
134+
|> Ecto.Changeset.change()
135+
|> Ecto.Changeset.put_embed(:emotions, updated_emotions)
136+
|> Repo.update()
137+
# virtual field can not be updated
138+
|> add_viewer_emotioned_ifneed(updated_emotions)
139+
end)
140+
|> Repo.transaction()
141+
|> upsert_comment_result
142+
end
143+
end
144+
145+
defp add_viewer_emotioned_ifneed({:error, error}, _), do: {:error, error}
146+
147+
defp add_viewer_emotioned_ifneed({:ok, comment}, emotions) do
148+
# Map.merge(comment, %{emotion: emotions})
149+
{:ok, Map.merge(comment, %{emotion: emotions})}
150+
end
151+
152+
defp upsert_comment_result({:ok, %{update_comment_emotion: result}}), do: {:ok, result}
153+
154+
defp upsert_comment_result({:error, _, result, _steps}) do
155+
{:error, result}
156+
end
157+
end

test/groupher_server/cms/article_comment_emotions_test.exs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ defmodule GroupherServer.Test.CMS.ArticleCommentEmotions do
7777
assert @default_emotions == emotions
7878
end
7979

80-
@tag :wip
80+
@tag :wip2
8181
test "can make emotion to comment", ~m(post user user2)a do
8282
parent_content = "parent comment"
8383
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, parent_content, user)
@@ -92,7 +92,30 @@ defmodule GroupherServer.Test.CMS.ArticleCommentEmotions do
9292
assert user_exist_in?(user2, emotions.latest_downvote_users)
9393
end
9494

95-
@tag :wip
95+
@tag :wip2
96+
test "can undo emotion to comment", ~m(post user user2)a do
97+
parent_content = "parent comment"
98+
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, parent_content, user)
99+
100+
{:ok, _} = CMS.emotion_to_comment(parent_comment.id, :downvote, user)
101+
{:ok, _} = CMS.emotion_to_comment(parent_comment.id, :downvote, user2)
102+
103+
{:ok, %{emotions: emotions}} = ORM.find(ArticleComment, parent_comment.id)
104+
105+
assert emotions.downvote_count == 2
106+
assert user_exist_in?(user, emotions.latest_downvote_users)
107+
assert user_exist_in?(user2, emotions.latest_downvote_users)
108+
109+
{:ok, _} = CMS.undo_emotion_to_comment(parent_comment.id, :downvote, user)
110+
{:ok, _} = CMS.undo_emotion_to_comment(parent_comment.id, :downvote, user2)
111+
112+
{:ok, %{emotions: emotions}} = ORM.find(ArticleComment, parent_comment.id)
113+
assert emotions.downvote_count == 0
114+
assert not user_exist_in?(user, emotions.latest_downvote_users)
115+
assert not user_exist_in?(user2, emotions.latest_downvote_users)
116+
end
117+
118+
@tag :wip3
96119
test "same user make same emotion to same comment", ~m(post user)a do
97120
parent_content = "parent comment"
98121
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, parent_content, user)

test/groupher_server/cms/article_comment_replies_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule GroupherServer.Test.CMS.ArticleCommentReplies do
3434
assert exist_in?(replyed_comment, parent_comment.replies)
3535
end
3636

37-
@tag :wip2
37+
@tag :wip3
3838
test "deleted comment can not be reply", ~m(post user user2)a do
3939
parent_content = "parent comment"
4040
reply_content = "reply comment"

test/groupher_server/cms/article_comment_test.exs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ defmodule GroupherServer.Test.CMS.ArticleComment do
4747
assert comment.meta |> Map.from_struct() |> Map.delete(:id) == @default_comment_meta
4848
end
4949

50-
@tag :wip2
50+
@tag :wip3
5151
test "comment can be updated", ~m(post user)a do
5252
{:ok, comment} = CMS.create_article_comment(:post, post.id, "post comment", user)
5353

@@ -565,7 +565,7 @@ defmodule GroupherServer.Test.CMS.ArticleComment do
565565
end
566566

567567
describe "[article comment delete]" do
568-
@tag :wip2
568+
@tag :wip3
569569
test "delete comment still exsit in paged list and content is gone", ~m(user post)a do
570570
total_count = 10
571571
page_number = 1
@@ -590,7 +590,7 @@ defmodule GroupherServer.Test.CMS.ArticleComment do
590590
assert deleted_comment.body_html == @delete_hint
591591
end
592592

593-
@tag :wip2
593+
@tag :wip3
594594
test "delete comment still update article's comments_count field", ~m(user post)a do
595595
{:ok, _comment} = CMS.create_article_comment(:post, post.id, "commment", user)
596596
{:ok, _comment} = CMS.create_article_comment(:post, post.id, "commment", user)
@@ -608,7 +608,7 @@ defmodule GroupherServer.Test.CMS.ArticleComment do
608608
assert post.article_comments_count == 4
609609
end
610610

611-
@tag :wip2
611+
@tag :wip3
612612
test "delete comment still delete pined record if needed", ~m(user post)a do
613613
total_count = 10
614614

0 commit comments

Comments
 (0)