-
Notifications
You must be signed in to change notification settings - Fork 499
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
added vote feature on comments (upvote, downvote) #22
base: master
Are you sure you want to change the base?
Changes from 1 commit
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 |
---|---|---|
@@ -1,11 +1,17 @@ | ||
package articles | ||
|
||
import ( | ||
"fmt" | ||
_ "fmt" | ||
"github.com/jinzhu/gorm" | ||
"github.com/wangzitian0/golang-gin-starter-kit/common" | ||
"github.com/wangzitian0/golang-gin-starter-kit/users" | ||
"golang-gin-realworld-example-app/common" | ||
"golang-gin-realworld-example-app/users" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/jinzhu/gorm" | ||
// "github.com/wangzitian0/golang-gin-starter-kit/users" | ||
// "github.com/wangzitian0/golang-gin-starter-kit/common" | ||
// "github.com/wangzitian0/golang-gin-starter-kit/users" | ||
) | ||
|
||
type ArticleModel struct { | ||
|
@@ -44,11 +50,22 @@ type TagModel struct { | |
|
||
type CommentModel struct { | ||
gorm.Model | ||
Article ArticleModel | ||
ArticleID uint | ||
Author ArticleUserModel | ||
AuthorID uint | ||
Body string `gorm:"size:2048"` | ||
Article ArticleModel | ||
ArticleID uint | ||
Author ArticleUserModel | ||
CommentVote []CommentModelVote `gorm:"foreignkey:CommentID"` | ||
AuthorID uint | ||
Body string `gorm:"size:2048"` | ||
} | ||
|
||
type CommentModelVote struct { | ||
CreatedAt time.Time | ||
UpdatedAt time.Time | ||
DeletedAt *time.Time | ||
UserID uint `gorm:"primary_key;auto_increment:false"` | ||
CommentID uint `gorm:"primary_key;auto_increment:false"` | ||
Comment on lines
+61
to
+62
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. The id might not be uint in some database, as we have used the orm. |
||
UpVote bool | ||
DownVote bool | ||
} | ||
|
||
func GetArticleUserModel(userModel users.UserModel) ArticleUserModel { | ||
|
@@ -267,3 +284,41 @@ func DeleteCommentModel(condition interface{}) error { | |
err := db.Where(condition).Delete(CommentModel{}).Error | ||
return err | ||
} | ||
|
||
func GetCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { | ||
db := common.GetDB() | ||
var commentVote CommentModelVote | ||
err := db.Where("user_id = ? AND comment_id = ?", userId, vote.CommentID).First(&commentVote).Error | ||
singh-gursharan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return commentVote, err | ||
} | ||
|
||
func CreateCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { | ||
db := common.GetDB() | ||
commentVote := CommentModelVote{ | ||
CommentID: vote.CommentID, | ||
UserID: userId, | ||
UpVote: vote.UpVote, | ||
DownVote: vote.DownVote, | ||
} | ||
err := db.Create(&commentVote).Error | ||
fmt.Printf("\n\nthis is in CreateCommentVote: %+v\n\n", commentVote) | ||
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. If a error happend, commentVote will be what?
|
||
return commentVote, err | ||
} | ||
|
||
func DeleteCommentVote(commentVote CommentModelVote) error { | ||
db := common.GetDB() | ||
err := db.Unscoped().Delete(&commentVote).Error | ||
return err | ||
} | ||
|
||
func UpdateCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { | ||
db := common.GetDB() | ||
voteModel, err := GetCommentVote(vote, userId) | ||
if err != nil { | ||
return voteModel, err | ||
} | ||
voteModel.UpVote = vote.UpVote | ||
voteModel.DownVote = vote.DownVote | ||
err2 := db.Save(&voteModel).Error | ||
return voteModel, err2 | ||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -2,11 +2,17 @@ package articles | |||
|
||||
import ( | ||||
"errors" | ||||
"github.com/wangzitian0/golang-gin-starter-kit/common" | ||||
"github.com/wangzitian0/golang-gin-starter-kit/users" | ||||
"gopkg.in/gin-gonic/gin.v1" | ||||
"fmt" | ||||
"golang-gin-realworld-example-app/common" | ||||
"golang-gin-realworld-example-app/users" | ||||
"net/http" | ||||
"strconv" | ||||
|
||||
// "github.com/wangzitian0/golang-gin-starter-kit/common" | ||||
singh-gursharan marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
// "github.com/wangzitian0/golang-gin-starter-kit/users" | ||||
|
||||
// "gopkg.in/gin-gonic/gin.v1" | ||||
"github.com/gin-gonic/gin" | ||||
) | ||||
|
||||
func ArticlesRegister(router *gin.RouterGroup) { | ||||
|
@@ -17,8 +23,74 @@ func ArticlesRegister(router *gin.RouterGroup) { | |||
router.DELETE("/:slug/favorite", ArticleUnfavorite) | ||||
router.POST("/:slug/comments", ArticleCommentCreate) | ||||
router.DELETE("/:slug/comments/:id", ArticleCommentDelete) | ||||
router.POST("/:slug/comments/:id/vote", ArticleCommentVotePost) | ||||
router.DELETE("/:slug/comments/:id/vote", ArticleCommentVoteDelete) | ||||
router.PUT("/:slug/comments/:id/vote", ArticleCommentVoteUpdate) | ||||
} | ||||
|
||||
func ArticleCommentVotePost(c *gin.Context) { | ||||
commentVoteValidator := CommentVoteValidator{} | ||||
if err := commentVoteValidator.Bind(c); err != nil { | ||||
c.JSON(http.StatusBadRequest, err.Error()) | ||||
return | ||||
} | ||||
userId := c.MustGet("my_user_id").(uint) | ||||
vote, err := CreateCommentVote(commentVoteValidator, userId) | ||||
if err != nil { | ||||
c.JSON(http.StatusConflict, gin.H{ | ||||
"error": err.Error(), | ||||
}) | ||||
return | ||||
} | ||||
serial := VoteSerializer{vote: vote} | ||||
c.JSON(http.StatusCreated, gin.H{ | ||||
"vote": serial.Response(), | ||||
}) | ||||
} | ||||
func ArticleCommentVoteUpdate(c *gin.Context) { | ||||
commentVoteValidator := CommentVoteValidator{} | ||||
if err := commentVoteValidator.Bind(c); err != nil { | ||||
c.JSON(http.StatusBadRequest, err.Error()) | ||||
return | ||||
} | ||||
userId := c.MustGet("my_user_id").(uint) | ||||
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. Can we use users.UserModel here?
We could get the user information by one retrieve of UserModel. |
||||
vote, err := UpdateCommentVote(commentVoteValidator, userId) | ||||
if err != nil { | ||||
c.JSON(http.StatusConflict, gin.H{ | ||||
"error": err.Error(), | ||||
}) | ||||
return | ||||
} | ||||
serial := VoteSerializer{vote: vote} | ||||
c.JSON(http.StatusOK, gin.H{ | ||||
"vote": serial.Response(), | ||||
}) | ||||
} | ||||
func ArticleCommentVoteDelete(c *gin.Context) { | ||||
commentVoteValidator := CommentVoteValidator{} | ||||
if err := commentVoteValidator.BindCommentId(c); err != nil { | ||||
c.JSON(http.StatusBadRequest, err.Error()) | ||||
return | ||||
} | ||||
userId := c.MustGet("my_user_id").(uint) | ||||
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. ditto |
||||
vote, err := GetCommentVote(commentVoteValidator, userId) | ||||
if err != nil { | ||||
c.JSON(http.StatusNotFound, gin.H{ | ||||
"error": err.Error(), | ||||
}) | ||||
return | ||||
} | ||||
if err := DeleteCommentVote(vote); err != nil { | ||||
c.JSON(http.StatusForbidden, gin.H{ | ||||
"error": err.Error(), | ||||
}) | ||||
return | ||||
} | ||||
c.JSON(http.StatusOK, gin.H{ | ||||
"success": "comment got deleted", | ||||
}) | ||||
|
||||
} | ||||
func ArticlesAnonymousRegister(router *gin.RouterGroup) { | ||||
router.GET("/", ArticleList) | ||||
router.GET("/:slug", ArticleRetrieve) | ||||
|
@@ -35,6 +107,7 @@ func ArticleCreate(c *gin.Context) { | |||
c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err)) | ||||
return | ||||
} | ||||
fmt.Printf("ArticleModelValidator: %+v\n", articleModelValidator) | ||||
//fmt.Println(articleModelValidator.articleModel.Author.UserModel) | ||||
|
||||
if err := SaveOne(&articleModelValidator.articleModel); err != nil { | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,41 @@ | ||
package articles | ||
|
||
import ( | ||
"fmt" | ||
"golang-gin-realworld-example-app/common" | ||
"golang-gin-realworld-example-app/users" | ||
|
||
"github.com/gosimple/slug" | ||
"github.com/wangzitian0/golang-gin-starter-kit/common" | ||
"github.com/wangzitian0/golang-gin-starter-kit/users" | ||
"gopkg.in/gin-gonic/gin.v1" | ||
// "github.com/wangzitian0/golang-gin-starter-kit/common" | ||
singh-gursharan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// "github.com/wangzitian0/golang-gin-starter-kit/users" | ||
// "gopkg.in/gin-gonic/gin.v1" | ||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
type ArticleModelValidator struct { | ||
Article struct { | ||
Title string `form:"title" json:"title" binding:"exists,min=4"` | ||
Title string `form:"title" json:"title" binding:"required"` | ||
Description string `form:"description" json:"description" binding:"max=2048"` | ||
Body string `form:"body" json:"body" binding:"max=2048"` | ||
Tags []string `form:"tagList" json:"tagList"` | ||
} `json:"article"` | ||
articleModel ArticleModel `json:"-"` | ||
} | ||
|
||
type CommentVoteValidator struct { | ||
CommentID uint `uri:"id" binding:"required"` | ||
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. Please use orm feature? |
||
UpVote bool `json:"up_vote"` | ||
DownVote bool `json:"down_vote"` | ||
} | ||
|
||
type CommentVoteError struct { | ||
err string | ||
} | ||
|
||
func (e CommentVoteError) Error() string { | ||
return e.err | ||
} | ||
|
||
func NewArticleModelValidator() ArticleModelValidator { | ||
return ArticleModelValidator{} | ||
} | ||
|
@@ -70,3 +89,31 @@ func (s *CommentModelValidator) Bind(c *gin.Context) error { | |
s.commentModel.Author = GetArticleUserModel(myUserModel) | ||
return nil | ||
} | ||
|
||
func (s *CommentVoteValidator) Bind(c *gin.Context) error { | ||
// commentID := c.Param("id")(int) | ||
// s.CommentID = commentID | ||
if err := c.ShouldBindUri(s); err != nil { | ||
return err | ||
} | ||
err := common.Bind(c, s) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("\n\n In Bind: %+v \n\n", s) | ||
if (s.DownVote && s.UpVote) || !(s.UpVote || s.DownVote) { | ||
err := CommentVoteError{err: "Either one of the UpVote or DownVote can be true not both."} | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (s *CommentVoteValidator) BindCommentId(c *gin.Context) error { | ||
// commentID := c.Param("id")(int) | ||
// s.CommentID = commentID | ||
if err := c.ShouldBindUri(s); err != nil { | ||
return err | ||
} | ||
fmt.Printf("\n\n In Bind: %+v \n\n", s) | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,12 @@ package common | |
|
||
import ( | ||
"fmt" | ||
|
||
"os" | ||
|
||
"github.com/jinzhu/gorm" | ||
_ "github.com/jinzhu/gorm/dialects/postgres" | ||
_ "github.com/jinzhu/gorm/dialects/sqlite" | ||
"os" | ||
) | ||
|
||
type Database struct { | ||
|
@@ -15,13 +18,15 @@ var DB *gorm.DB | |
|
||
// Opening a database and save the reference to `Database` struct. | ||
func Init() *gorm.DB { | ||
db, err := gorm.Open("sqlite3", "./../gorm.db") | ||
// db, err := gorm.Open("sqlite3", "./../gorm.db") | ||
db, err := gorm.Open("postgres", "host=localhost port=5432 user=postgres dbname=realworld password=postgres") | ||
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. Why? The sqlite3 is easy for newcomers. |
||
if err != nil { | ||
fmt.Println("db err: ", err) | ||
} | ||
db.DB().SetMaxIdleConns(10) | ||
//db.LogMode(true) | ||
db.LogMode(true) | ||
DB = db | ||
fmt.Printf("db is: %+v\n", *DB) | ||
return DB | ||
} | ||
|
||
|
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.
As we want to provide a
best practice
, can we use http://gorm.io/docs/conventions.html?like
golang-gin-realworld-example-app/articles/models.go
Line 12 in d5d6955