Skip to content

Commit f9cc129

Browse files
authored
Release v21.12.2023
Release v21.12.2023
2 parents 73d5739 + 894d9cc commit f9cc129

23 files changed

+942
-64
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ gem 'blazer'
6262

6363
gem 'rack-cors'
6464

65+
gem 'friendly_id'
66+
6567
# Use Sass to process CSS
6668
# gem "sassc-rails"
6769

Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ GEM
135135
railties (>= 5.0.0)
136136
faker (3.2.2)
137137
i18n (>= 1.8.11, < 2)
138+
friendly_id (5.5.1)
139+
activerecord (>= 4.0.0)
138140
globalid (1.2.1)
139141
activesupport (>= 6.1)
140142
grape (2.0.0)
@@ -329,6 +331,7 @@ DEPENDENCIES
329331
devise-jwt
330332
factory_bot_rails
331333
faker
334+
friendly_id
332335
grape
333336
grape-swagger
334337
grape_logging

app/api/web/discussions_api.rb

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ def format_discussion(discussion)
66
{
77
id: discussion.id,
88
title: discussion.title,
9+
slug: discussion.slug,
910
content: discussion.content,
1011
total_comments: discussion.total_comments,
1112
created_at: discussion.created_at.to_fs(:ymd_hms),
@@ -71,10 +72,10 @@ def format_comment(comment)
7172

7273
desc 'Get a discussion'
7374
params do
74-
requires :id, type: Integer, desc: 'Discussion id'
75+
requires :id, type: String, desc: 'Discussion :id/:slug'
7576
end
7677
get ':id' do
77-
discussion = Discussion.find(params[:id])
78+
discussion = Discussion.friendly.find(params[:id])
7879
if discussion
7980
status 200
8081
{
@@ -93,10 +94,11 @@ def format_comment(comment)
9394
security: [access_token: {}]
9495
params do
9596
requires :content, type: String, desc: 'Discussion content', allow_blank: false
97+
requires :title, type: String, desc: 'Discussion title', allow_blank: false
9698
end
9799
post do
98100
authenticate_user!
99-
discussion = current_user.discussions.new(content: params[:content], status: 'approved')
101+
discussion = current_user.discussions.new(content: params[:content], status: 'approved', title: params[:title])
100102
if discussion.save
101103
status 200
102104
{
@@ -115,12 +117,12 @@ def format_comment(comment)
115117
desc 'Update a discussion',
116118
security: [access_token: {}]
117119
params do
118-
requires :id, type: Integer, desc: 'Discussion id'
120+
requires :id, type: String, desc: 'Discussion :id/:slug'
119121
requires :content, type: String, desc: 'Discussion content', allow_blank: false
120122
end
121123
put ':id' do
122124
authenticate_user!
123-
discussion = current_user.discussions.find_by(id: params[:id])
125+
discussion = current_user.discussions.friendly.find(params[:id])
124126
if discussion.update(content: params[:content])
125127
status 200
126128
{
@@ -139,11 +141,15 @@ def format_comment(comment)
139141
desc 'Reject a discussion',
140142
security: [access_token: {}]
141143
params do
142-
requires :id, type: Integer, desc: 'Discussion id'
144+
requires :id, type: String, desc: 'Discussion :id/:slug'
143145
end
144146
put ':id/reject' do
145147
authenticate_user!
146-
discussion = current_user.discussions.approved.find_by(id: params[:id])
148+
if current_user.admin?
149+
discussion = Discussion.friendly.find(params[:id])
150+
else
151+
discussion = current_user.discussions.friendly.find(params[:id])
152+
end
147153
if discussion.update(status: 'rejected')
148154
status 200
149155
{
@@ -162,12 +168,17 @@ def format_comment(comment)
162168
desc 'Delete a discussion',
163169
security: [access_token: {}]
164170
params do
165-
requires :id, type: Integer, desc: 'Discussion id'
171+
requires :id, type: String, desc: 'Discussion :id/:slug'
166172
end
167173
delete ':id' do
168174
authenticate_user!
169-
discussion = current_user.discussions.find_by(id: params[:id])
170-
if discussion.destroy
175+
if current_user.admin?
176+
discussion = Discussion.friendly.find_by(id: params[:id]) || Discussion.friendly.find_by(slug: params[:id])
177+
else
178+
discussion = current_user.discussions.friendly.find_by(id: params[:id]) || current_user.discussions.friendly.find_by(slug: params[:id])
179+
end
180+
if discussion
181+
discussion.destroy
171182
status 200
172183
{
173184
success: true,
@@ -177,17 +188,17 @@ def format_comment(comment)
177188
status 400
178189
{
179190
success: false,
180-
errors: discussion.errors.full_messages
191+
error: 'Discussion not found'
181192
}
182193
end
183194
end
184195

185196
desc 'Get all comments of a discussion'
186197
params do
187-
requires :id, type: Integer, desc: 'Discussion id'
198+
requires :id, type: String, desc: 'Discussion :id/:slug'
188199
end
189200
get ':id/comments' do
190-
discussion = Discussion.approved.find_by(id: params[:id])
201+
discussion = Discussion.approved.friendly.find(params[:id])
191202
if discussion
192203
status 200
193204
{
@@ -206,12 +217,12 @@ def format_comment(comment)
206217
desc 'Create a comment of a discussion',
207218
security: [access_token: {}]
208219
params do
209-
requires :id, type: Integer, desc: 'Discussion id'
220+
requires :id, type: String, desc: 'Discussion :id/:slug'
210221
requires :content, type: String, desc: 'Comment content', allow_blank: false
211222
end
212223
post ':id/comments' do
213224
authenticate_user!
214-
discussion = Discussion.approved.find_by(id: params[:id])
225+
discussion = Discussion.approved.friendly.find(params[:id])
215226
if discussion
216227
comment = discussion.comments.new(user: current_user, content: params[:content], status: 'approved')
217228
if comment.save
@@ -239,13 +250,13 @@ def format_comment(comment)
239250
desc 'Update a comment of a discussion',
240251
security: [access_token: {}]
241252
params do
242-
requires :id, type: Integer, desc: 'Discussion id'
253+
requires :id, type: String, desc: 'Discussion :id/:slug'
243254
requires :comment_id, type: Integer, desc: 'Comment id'
244255
requires :content, type: String, desc: 'Comment content', allow_blank: false
245256
end
246257
put ':id/comments/:comment_id' do
247258
authenticate_user!
248-
discussion = Discussion.approved.find_by(id: params[:id])
259+
discussion = Discussion.approved.friendly.find(params[:id])
249260
if discussion
250261
comment = discussion.comments.find_by(id: params[:comment_id])
251262
if comment.update(content: params[:content])
@@ -273,12 +284,12 @@ def format_comment(comment)
273284
desc 'Reject a comment of a discussion',
274285
security: [access_token: {}]
275286
params do
276-
requires :id, type: Integer, desc: 'Discussion id'
287+
requires :id, type: String, desc: 'Discussion :id/:slug'
277288
requires :comment_id, type: Integer, desc: 'Comment id'
278289
end
279290
put ':id/comments/:comment_id/reject' do
280291
authenticate_user!
281-
discussion = Discussion.approved.find_by(id: params[:id])
292+
discussion = Discussion.approved.friendly.find(params[:id])
282293
if discussion
283294
comment = discussion.comments.approved.find_by(id: params[:comment_id]).update(status: 'rejected')
284295
if comment
@@ -306,12 +317,12 @@ def format_comment(comment)
306317
desc 'Delete a comment of a discussion',
307318
security: [access_token: {}]
308319
params do
309-
requires :id, type: Integer, desc: 'Discussion id'
320+
requires :id, type: String, desc: 'Discussion :id/:slug'
310321
requires :comment_id, type: Integer, desc: 'Comment id'
311322
end
312323
delete ':id/comments/:comment_id' do
313324
authenticate_user!
314-
discussion = Discussion.approved.find_by(id: params[:id])
325+
discussion = Discussion.approved.friendly.find(params[:id])
315326
if discussion
316327
comment = discussion.comments.find_by(id: params[:comment_id])
317328
if comment.destroy

app/api/web/posts_api.rb

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class Web::PostsAPI < Grape::API
55
def format_post(post)
66
{
77
id: post.id,
8+
slug: post.slug,
89
title: post.title,
910
body: post.body,
1011
total_view: post.total_view,
@@ -57,10 +58,10 @@ def format_post(post)
5758

5859
desc 'Get a post'
5960
params do
60-
requires :id, type: Integer, desc: 'Post id'
61+
requires :id, type: String, desc: 'Post id/Post slug'
6162
end
6263
get ':id' do
63-
post = Post.find_by(id: params[:id])
64+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
6465
if post
6566
post.update(total_view: post.total_view + 1)
6667
status 200
@@ -112,13 +113,19 @@ def format_post(post)
112113
desc 'Update a post',
113114
security: [access_token: {}]
114115
params do
115-
requires :id, type: Integer, desc: 'Post id'
116+
requires :id, type: String, desc: 'Post id/Post slug'
116117
optional :new_title, type: String, desc: 'New post title'
117118
optional :new_body, type: String, desc: 'New post body'
118119
end
119120
put ':id' do
120121
authenticate_user!
121-
post = current_user.posts.find_by(id: params[:id])
122+
123+
if current_user.admin?
124+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
125+
else
126+
post = current_user.posts.friendly.find_by(id: params[:id]) || current_user.posts.friendly.find_by(slug: params[:id])
127+
end
128+
122129
if post
123130
post.update({
124131
title: params[:new_title],
@@ -133,26 +140,52 @@ def format_post(post)
133140
status 400
134141
{
135142
success: false,
136-
error: 'Post cannot be updated'
143+
error: 'You are not authorized'
144+
}
145+
end
146+
end
147+
148+
desc 'Reject a post',
149+
security: [access_token: {}]
150+
params do
151+
requires :id, type: String, desc: 'Post :id/:slug'
152+
end
153+
put '/:id/reject' do
154+
authenticate_user!
155+
156+
post = current_user.posts.friendly.find_by(id: params[:id]) || current_user.posts.friendly.find_by(slug: params[:id])
157+
158+
if post
159+
post.update(status: 'rejected')
160+
status 200
161+
{
162+
success: true,
163+
message: 'Post rejected successfully'
164+
}
165+
else
166+
status 400
167+
{
168+
success: false,
169+
error: 'Post cannot be rejected'
137170
}
138171
end
139172
end
140173

141174
desc 'Delete a post',
142175
security: [access_token: {}]
143176
params do
144-
requires :id, type: Integer, desc: 'Post id'
177+
requires :id, type: String, desc: 'Post :id/:slug'
145178
end
146179
delete ':id' do
147180
authenticate_user!
181+
148182
if current_user.admin?
149-
post = Post.find_by(id: params[:id])
183+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
150184
else
151-
post = current_user.posts.find_by(id: params[:id])
185+
return error!('You are not authorized', 400)
152186
end
153187

154-
if post
155-
post.update(status: 'deleted')
188+
if post.destroy
156189
status 200
157190
{
158191
success: true,
@@ -182,12 +215,14 @@ def format_post(post)
182215
desc 'Approve a post',
183216
security: [access_token: {}]
184217
params do
185-
requires :id, type: Integer, desc: 'Post id'
218+
requires :id, type: String, desc: 'Post :id/:slug'
186219
end
187-
put '/approve/:id' do
220+
put '/:id/approve' do
188221
authenticate_user!
222+
189223
if current_user.admin?
190-
post = Post.find_by(id: params[:id])
224+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
225+
191226
if post
192227
post.update(status: 'approved')
193228
status 200
@@ -196,6 +231,7 @@ def format_post(post)
196231
message: 'Post approved successfully'
197232
}
198233
end
234+
199235
else
200236
status 400
201237
{
@@ -207,11 +243,17 @@ def format_post(post)
207243

208244
desc 'Get a list feedbacks of a post'
209245
params do
210-
requires :id, type: Integer, desc: 'Post id'
246+
requires :id, type: String, desc: 'Post :id/:slug'
211247
end
212248
get '/:id/feedbacks' do
213-
feedbacks = Post.find_by(id: params[:id])&.feedbacks
214-
return status 400 unless feedbacks
249+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
250+
251+
if post
252+
feedbacks = post.feedbacks
253+
else
254+
return error!('Post not found', 400)
255+
end
256+
215257
status 200
216258
{
217259
success: true,
@@ -230,13 +272,13 @@ def format_post(post)
230272
desc 'Create a feedback for a post',
231273
security: [access_token: {}]
232274
params do
233-
requires :id, type: Integer, desc: 'Post id'
275+
requires :id, type: String, desc: 'Post :id/:slug'
234276
requires :content, type: String, desc: 'Feedback content', allow_blank: false
235277
end
236278
post '/:id/feedbacks' do
237279
authenticate_user!
238-
post = Post.find_by(id: params[:id])
239-
return status 400 unless post
280+
post = Post.friendly.find_by(id: params[:id]) || Post.friendly.find_by(slug: params[:id])
281+
return error!('Post not found', 400) unless post
240282
feedback = post.feedbacks.new({
241283
user_id: current_user.id,
242284
content: params[:content]

app/api/web/users_api.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Web::UsersAPI < Grape::API
3232
{
3333
id: post.id,
3434
title: post.title,
35+
slug: post.slug,
3536
total_views: post.total_view,
3637
created_at: post.created_at.to_fs(:ymd_hms),
3738
}

app/models/comment.rb

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,4 @@ class Comment < ApplicationRecord
99

1010
scope :approved, -> { where(status: 'approved') }
1111

12-
def self.create_comment(user, linked_object, body)
13-
comment = Comment.new
14-
comment.user = user
15-
comment.linked_object = linked_object
16-
comment.body = body
17-
comment.save
18-
comment
19-
end
20-
21-
def self.delete_comment(user, comment)
22-
if user == comment.user
23-
comment.destroy
24-
return true
25-
end
26-
false
27-
end
2812
end

0 commit comments

Comments
 (0)