-
-
Notifications
You must be signed in to change notification settings - Fork 702
Add solution for gin challenge-1-basic-routing by AlexO-85 #708
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
Add solution for gin challenge-1-basic-routing by AlexO-85 #708
Conversation
WalkthroughA Gin-based REST API implementing user CRUD operations with in-memory storage. Adds User and Response data models, six HTTP handlers for standard CRUD and search routes, in-memory user storage with seeding, validation logic, and standardized error responses on localhost:8080. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server as Gin Server
participant Storage as In-Memory Storage
Client->>Server: GET /users/:id
Server->>Storage: findUserByID(id)
alt User Found
Storage-->>Server: *User, index
Server-->>Client: 200 OK + Response{Success: true, Data: User}
else User Not Found
Storage-->>Server: nil, -1
Server-->>Client: 404 Not Found + Response{Success: false, Error: "not found"}
end
Client->>Server: POST /users (JSON: Name, Email, Age)
Server->>Server: Validate input
alt Validation Success
Server->>Storage: Append User with nextID++
Storage-->>Server: User created
Server-->>Client: 201 Created + Response{Success: true, Data: User}
else Validation Failed
Server-->>Client: 400 Bad Request + Response{Success: false, Error: "..."}
end
Client->>Server: GET /users/search?name=John
Server->>Storage: Iterate & match (case-insensitive)
Storage-->>Server: Matching users []User
Server-->>Client: 200 OK + Response{Success: true, Data: []User}
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Pre-merge checks✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 3
🧹 Nitpick comments (1)
packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go (1)
68-99: Consider extracting error response creation to reduce duplication.The error response creation pattern is repeated across multiple handlers. You could optionally create a helper function to reduce duplication:
func errorResponse(c *gin.Context, statusCode int, errorMsg string, details ...string) { response := Response{ Success: false, Error: errorMsg, Code: statusCode, } if len(details) > 0 { response.Message = details[0] } c.IndentedJSON(statusCode, response) }This is a nice-to-have improvement that can be deferred.
Also applies to: 128-176, 179-213
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go(1 hunks)
🔇 Additional comments (9)
packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go (9)
1-9: LGTM!Package declaration and imports are appropriate for the implemented functionality.
11-17: LGTM!User struct is well-defined with appropriate JSON and validation tags.
19-26: LGTM!Response struct provides a consistent API response format. The Code field is somewhat redundant with the HTTP status code but doesn't cause issues.
28-34: LGTM!In-memory storage is properly initialized with seed data.
58-65: LGTM!Handler correctly returns all users with appropriate response structure.
67-99: LGTM!Handler correctly parses the ID parameter, validates format, and returns appropriate responses for success and error cases.
178-213: LGTM!Handler correctly deletes the user and returns appropriate responses. Performing the deletion after sending the response is acceptable for this in-memory implementation.
215-243: LGTM!Search handler correctly validates the required query parameter and performs case-insensitive substring matching. Returning an empty slice when no matches are found is good API design.
245-253: LGTM!Helper function correctly returns a pointer to the user in the slice and its index, enabling efficient lookups and in-place updates.
| func main() { | ||
| router := gin.Default() | ||
|
|
||
| // TODO: Setup routes | ||
| // GET /users - Get all users | ||
| router.GET("/users", getAllUsers) | ||
| // GET /users/:id - Get user by ID | ||
| router.GET("/users/:id", getUserByID) | ||
| // POST /users - Create new user | ||
| router.POST("/users", createUser) | ||
| // PUT /users/:id - Update user | ||
| router.PUT("/users/:id", updateUser) | ||
| // DELETE /users/:id - Delete user | ||
| router.DELETE("/users/:id", deleteUser) | ||
| // GET /users/search - Search users by name | ||
| router.GET("/users/search", searchUsers) | ||
|
|
||
| router.Run("localhost:8080") | ||
| } |
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.
Fix route registration order to prevent conflict.
The route /users/search (line 51) is registered after /users/:id (line 43). In Gin's router, parameterized routes like :id match any path segment, including "search". This means requests to /users/search will be incorrectly handled by getUserByID with id="search", and the search endpoint will never be reached.
Apply this diff to register the specific route before the parameterized one:
// GET /users - Get all users
router.GET("/users", getAllUsers)
+ // GET /users/search - Search users by name
+ router.GET("/users/search", searchUsers)
// GET /users/:id - Get user by ID
router.GET("/users/:id", getUserByID)
// POST /users - Create new user
router.POST("/users", createUser)
// PUT /users/:id - Update user
router.PUT("/users/:id", updateUser)
// DELETE /users/:id - Delete user
router.DELETE("/users/:id", deleteUser)
- // GET /users/search - Search users by name
- router.GET("/users/search", searchUsers)🤖 Prompt for AI Agents
In packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go
around lines 36 to 54, the parameterized route router.GET("/users/:id",
getUserByID) is registered before the specific route router.GET("/users/search",
searchUsers), causing "/users/search" to be captured as an id; move the
router.GET("/users/search", searchUsers) registration so it appears before
router.GET("/users/:id", getUserByID) to ensure the specific search route is
matched first.
| // createUser handles POST /users | ||
| func createUser(c *gin.Context) { | ||
| var user User | ||
|
|
||
| if err := c.ShouldBindJSON(&user); err != nil { | ||
| response := Response{ | ||
| Success: false, | ||
| Error: "Bas request", | ||
| Message: err.Error(), | ||
| Code: http.StatusBadRequest, | ||
| } | ||
| c.IndentedJSON(http.StatusBadRequest, response) | ||
| return | ||
| } | ||
|
|
||
| user.ID = nextID | ||
| users = append(users, user) | ||
| nextID++ | ||
|
|
||
| response := Response{ | ||
| Success: true, | ||
| Data: user, | ||
| } | ||
| c.IndentedJSON(http.StatusCreated, response) | ||
| } |
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.
Fix typo in error message.
Line 108 contains a typo: "Bas request" should be "Bad request".
Apply this diff:
response := Response{
Success: false,
- Error: "Bas request",
+ Error: "Bad request",
Message: err.Error(),
Code: http.StatusBadRequest,
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // createUser handles POST /users | |
| func createUser(c *gin.Context) { | |
| var user User | |
| if err := c.ShouldBindJSON(&user); err != nil { | |
| response := Response{ | |
| Success: false, | |
| Error: "Bas request", | |
| Message: err.Error(), | |
| Code: http.StatusBadRequest, | |
| } | |
| c.IndentedJSON(http.StatusBadRequest, response) | |
| return | |
| } | |
| user.ID = nextID | |
| users = append(users, user) | |
| nextID++ | |
| response := Response{ | |
| Success: true, | |
| Data: user, | |
| } | |
| c.IndentedJSON(http.StatusCreated, response) | |
| } | |
| // createUser handles POST /users | |
| func createUser(c *gin.Context) { | |
| var user User | |
| if err := c.ShouldBindJSON(&user); err != nil { | |
| response := Response{ | |
| Success: false, | |
| Error: "Bad request", | |
| Message: err.Error(), | |
| Code: http.StatusBadRequest, | |
| } | |
| c.IndentedJSON(http.StatusBadRequest, response) | |
| return | |
| } | |
| user.ID = nextID | |
| users = append(users, user) | |
| nextID++ | |
| response := Response{ | |
| Success: true, | |
| Data: user, | |
| } | |
| c.IndentedJSON(http.StatusCreated, response) | |
| } |
🤖 Prompt for AI Agents
In packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go
around lines 101 to 125, there's a typo in the error response string "Bas
request" at line 108; update that string to "Bad request" so the Response.Error
field contains the correct message, then run gofmt/quick vet to ensure no other
changes are needed.
| // updateUser handles PUT /users/:id | ||
| func updateUser(c *gin.Context) { | ||
| idStr := c.Param("id") | ||
| // Handle invalid ID format | ||
| id, err := strconv.Atoi(idStr) | ||
| if err != nil { | ||
| response := Response{ | ||
| Success: false, | ||
| Error: "User ID format is wrong", | ||
| Message: err.Error(), | ||
| Code: http.StatusBadRequest, | ||
| } | ||
| c.IndentedJSON(http.StatusBadRequest, response) | ||
| return | ||
| } | ||
|
|
||
| var newUser User | ||
|
|
||
| if err := c.ShouldBindJSON(&newUser); err != nil { | ||
| response := Response{ | ||
| Success: false, | ||
| Error: "Bas request", | ||
| Message: err.Error(), | ||
| Code: http.StatusBadRequest, | ||
| } | ||
| c.IndentedJSON(http.StatusBadRequest, response) | ||
| return | ||
| } | ||
|
|
||
| if user, _ := findUserByID(id); user != nil { | ||
| user.Name = newUser.Name | ||
| user.Email = newUser.Email | ||
| user.Age = newUser.Age | ||
|
|
||
| response := Response{ | ||
| Success: true, | ||
| Data: user, | ||
| } | ||
| c.IndentedJSON(http.StatusOK, response) | ||
| return | ||
| } | ||
|
|
||
| response := Response{ | ||
| Success: false, | ||
| Error: "User not found", | ||
| Code: http.StatusNotFound, | ||
| } | ||
|
|
||
| c.IndentedJSON(http.StatusNotFound, response) | ||
| } |
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.
Fix typo in error message.
Line 148 contains the same typo: "Bas request" should be "Bad request".
Apply this diff:
response := Response{
Success: false,
- Error: "Bas request",
+ Error: "Bad request",
Message: err.Error(),
Code: http.StatusBadRequest,
}🤖 Prompt for AI Agents
packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.go lines
127-176: the error response for JSON binding has a typo "Bas request"; update
the Response.Error string to "Bad request" (fix the typo) so the error reads
"Bad request" before returning the 400 response.
gin challenge-1-basic-routing Solution
Submitted by: @AlexO-85
Package: gin
Challenge: challenge-1-basic-routing
Description
This PR contains my solution for gin challenge-1-basic-routing.
Changes
packages/gin/challenge-1-basic-routing/submissions/AlexO-85/solution.goTesting
Thank you for reviewing my submission! 🚀