해당 게시글에 좋아요를 누른 사람을 기록 할 테이블이 필요하다.
사용자는 많은 게시글을 좋아요 할 수 있고
게시글은 많은 유저들에게 좋아요를 받을 수 있다.
따라서 사용자-게시글 간 모델 설정이 필요하다.
/models/user.js
...
static associate(db) {
db.User.hasMany(db.Post);
db.User.belongsToMany(db.User, {
foreignKey: 'followingId',
as: 'Followers',
through: 'Follow',
});
db.User.belongsToMany(db.User, {
foreignKey: 'followerId',
as: 'Followings',
through: 'Follow',
});
db.User.belongsToMany(db.Post,{through:'Like'});
}
/models/post.js
...
static associate(db) {
db.Post.belongsTo(db.User);
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Post.belongsToMany(db.User,{through:'Like', as:'Liker'});
}
post와 user를 다대다 관계를 설정 하면 Like테이블이 생성된다.
메인에 게시글들을 불러 올 때 게시글의 작성자뿐만 아니라 좋아요를 한 사람을 불러온다.
같은 모델을 불러 올 때 as를 사용하여 구분한다.
/routes/page.js
...
router.get('/', (req,res,next)=>{
Post.findAll({
include:[{
model: User,
attributes:['id','nick'],
},{
model: User,
attributes:['id','nick'],
as: 'Liker',
}],
})
.then((posts)=>{
res.render('main',{
title:'NodeBird',
twits:posts,
user:req.user,
});
})
.catch((error)=>{
console.error(error);
next(error);
});
});
...
프론트에 좋아요 버튼을 생성 해준다.
// main.html
...
{% for twit in twits %}
<div class="twit">
<input type="hidden" value="{{twit.id}}" class="twit-id">
...
{%set isLiked = 'false' %}
{%for like in twit.Liker %}
{%if like.id === user.id %}
{%set isLiked = 'true'%}
{% endif %}
{% endfor %}
{%if isLiked ==='false' %}
<button class="like btn abled">좋아요</button>
{% elif isLiked ==='true' %}
<button class="unLike btn">좋아요 취소</button>
{% endif %}
이 부분이 좀 마음에 안드는데 다른 방법을 찾지 못해 이렇게 했다..( 더 깔끔한 방법을 아시는 분은 알려주세요)
좋아요 정보를 담기 위해 게시글 번호가 필요해서 hidden옵션으로 만들었다.
isLiked변수를 생성해서 false를 지정 해 둔다.
해당 게시글을 좋아요 누른 사람들 중에 사용자의 아이디가 포함 되어 있으면 isLiked를 true로 변경한다.
Liker들을 모두 탐색 후
isLiked변수의 값에 따라 좋아요 혹은 좋아요 취소 버튼이 보이게 한다.
js도 추가 해 준다.
// main.html
...
document.querySelectorAll('.like').forEach(function(tag) {
tag.addEventListener('click', function() {
const myId = document.querySelector('#my-id');
const twitId = tag.parentNode.querySelector('.twit-id').value;
if (myId) {
axios.post(`/post/${twitId}/like`)
.then(() => {
location.reload();
})
.catch((err) => {
console.error(err);
});
}
});
});
document.querySelectorAll('.unLike').forEach(function(tag) {
tag.addEventListener('click', function() {
const myId = document.querySelector('#my-id');
const twitId = tag.parentNode.querySelector('.twit-id').value;
if (myId) {
axios.delete(`/post/${twitId}/unLike`)
.then(() => {
location.reload();
})
.catch((err) => {
console.error(err);
});
}
});
});
...
/routes/post.js 에 좋아요, 좋아요 취소 라우터를 만들어준다.
/routes/post.js
...
router.post('/:id/like',async(req,res,next)=>{
try{
const post=await Post.findOne({where:{id:req.params.id}});
await post.addLiker(req.user.id);
res.send('OK');
} catch(error){
console.error(error);
next(error);
}
});
router.delete('/:id/unLike',async(req,res,next)=>{
try{
const post=await Post.findOne({where:{id:req.params.id}});
await post.removeLiker(req.user.id);
res.send('OK');
} catch(error){
console.error(error);
next(error);
}
});
좋아요를 하면 요청한 파라미터 id에 맞는 게시글을 찾은 후에 Liker를 추가 한다.
좋아요 취소를 누르면 삭제한다.