-
Notifications
You must be signed in to change notification settings - Fork 3
[feat] 문제 수정, 삭제 API 구현 #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3f1fca6
ade4517
180d751
668b2a7
d9c5bc1
648f970
852c13a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package io.f1.backend.domain.question.api; | ||
|
|
||
| import io.f1.backend.domain.question.app.QuestionService; | ||
| import io.f1.backend.domain.question.dto.QuestionUpdateRequest; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PutMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/questions") | ||
| @RequiredArgsConstructor | ||
| public class QuestionController { | ||
|
|
||
| private final QuestionService questionService; | ||
|
|
||
| @PutMapping("/{questionId}") | ||
| public ResponseEntity<Void> updateQuestion( | ||
| @PathVariable Long questionId, @RequestBody QuestionUpdateRequest request) { | ||
|
|
||
| if (request.content() != null) { | ||
| questionService.updateQuestionContent(questionId, request.content()); | ||
| } | ||
|
|
||
| if (request.content() != null) { | ||
| questionService.updateQuestionAnswer(questionId, request.answer()); | ||
| } | ||
|
|
||
| return ResponseEntity.noContent().build(); | ||
| } | ||
|
|
||
| @DeleteMapping("/{questionId}") | ||
| public ResponseEntity<Void> deleteQuestion(@PathVariable Long questionId) { | ||
| questionService.deleteQuestion(questionId); | ||
|
|
||
| return ResponseEntity.noContent().build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package io.f1.backend.domain.question.dto; | ||
|
|
||
| public record QuestionUpdateRequest(String content, String answer) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package io.f1.backend.global.validation; | ||
|
|
||
| import jakarta.validation.Constraint; | ||
| import jakarta.validation.Payload; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Documented | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L5-참고의견] |
||
| @Constraint(validatedBy = TrimmedSizeValidator.class) | ||
| @Target({ElementType.FIELD, ElementType.PARAMETER}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| public @interface TrimmedSize { | ||
|
|
||
| String message() default "공백 제외 길이가 {min}자 이상 {min}자 이하여야 합니다."; | ||
|
|
||
| int min() default 0; | ||
|
|
||
| int max() default 50; | ||
|
|
||
| Class<?>[] groups() default {}; | ||
|
|
||
| Class<? extends Payload>[] payload() default {}; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package io.f1.backend.global.validation; | ||
|
|
||
| import jakarta.validation.ConstraintValidator; | ||
| import jakarta.validation.ConstraintValidatorContext; | ||
|
|
||
| public class TrimmedSizeValidator implements ConstraintValidator<TrimmedSize, String> { | ||
|
|
||
| private int min; | ||
| private int max; | ||
|
|
||
| @Override | ||
| public void initialize(TrimmedSize constraintAnnotation) { | ||
| this.min = constraintAnnotation.min(); | ||
| this.max = constraintAnnotation.max(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isValid(String value, ConstraintValidatorContext context) { | ||
| if (value == null) return true; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L5-참고의견]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵 맞습니다 ! null 검사는 현재 유효성 검사를 할 때, 그래서 완전한 빈 문자열이나 null이 들어왔을 땐 이렇게 역할이 분리되는 것이 맞다고 생각하여 따로 null 처리는 하지 않았습니다 !
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TrimmedSize라는 어노테이션이 개발자의 실수 등의 이유로 단독으로 사용되는 경우를 생각했었는데, |
||
|
|
||
| String trimmed = value.trim(); | ||
| int length = trimmed.length(); | ||
|
|
||
| return length >= min && length <= max; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validate 분리되어있는거 편--안하네요 👍