Rails와 Ajax를 사용하고 싶은 기능의 비동기 통신

전직 활동을 위해 개인 앱을 개발 중입니다.
이번에는 Rails와 Ajax를 사용하여 좋아하는 기능을 비동기화했습니다.

Ajax에서는 jQuery를 사용하기 때문에 jQuery를 사용할 수 있도록 해 두는 사전 준비가 필요합니다. 그것은 참고 기사를 참조하십시오. 아래의 설명은 그것이 설정된 후의 이야기입니다.



실현된 기능



· "좋아요"버튼을 누르면 다시로드하지 않고 "좋아요 취소"로 표시가 바뀝니다.
· "좋아요"버튼을 누르면 다시로드하지 않고 liques 테이블에 데이터가 하나 추가됩니다.
· "좋아요"버튼을 누르면 다시로드하지 않고 좋아하는 숫자가 하나 증가합니다.
※그 반대도

이 코드로 잘 작동했습니다.



컨트롤러 (likes_controller.rb)



likes_controller.rb
class LikesController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    @like = current_user.likes.build(post_id: params[:post_id])
    @like.save
    @likeCounts = Like.where(post_id: params[:post_id])
  end

  def destroy
    @post = Post.find(params[:post_id])
    @like = Like.find_by(post_id: params[:post_id], user_id: current_user.id)
    @like.destroy
    @likeCounts = Like.where(post_id: params[:post_id])
  end

end

개별 게시 페이지 (위 이미지 페이지)



show.html.haml
.like
  = render partial: "likes/like", locals: {post: @post}

부분 템플릿(_like.html.haml)



_like.html.haml
- if user_signed_in?
  - if current_user.already_liked?(post)
    = button_to 'いいねを取り消す', post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true
  - else
    = button_to 'いいね', post_likes_path(post.id), method: :post, remote: true
.likeCounts
  いいね数:
  = post.likes.count

업데이트하고 싶은 부분의 뷰(좋을 때)



create.js.erb
$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");

업데이트하고 싶은 부분의 뷰(좋아요를 취소할 때)



destroy.js.erb
$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");

JavaScript가 움직이는 메커니즘



· link_to 또는 button_to에는 :remote 옵션( remote: true )이 있다. button_toremote: true를 추가하면 js 형식의 요청을 보낼 수 있습니다.
= button_to 'いいね', post_likes_path(post.id), method: :post, remote: true

참고 : Rails 가이드

비동기 통신 흐름



1. "좋아요"버튼을 누른다
2.아래 링크에서 likes#create에 js 형식으로 요청이 건너 뜁니다.
= button_to 'いいね', post_likes_path(post.id), method: :post, remote: true

3.likes 컨트롤러의 create 액션이 움직이고 좋아요가 저장된다. Like 모델을 통해 데이터베이스에 추가 (재로드하지 않고)
4. 갱신하고 싶은 부분의 페이지 create.js.erb , destroy.js.erb 가 응답으로서 돌려주어진다. .html (jQuery의 html 메소드)는, .like (like 클래스)의 부분을 html의 뒤의 ( )내에 옮겨놓는 역할을 한다.

이번에 고생한 곳



1. 부분 템플릿 이해

create.js.erb
$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");

partial 옵션: 부분 템플릿을 호출합니다. 이번에는 likes 폴더의 _like.html.haml을 호출하고 싶기 때문에 likes/like
locals 옵션 : 부분 템플리트에서 {}의 왼쪽을 변수로 사용할 수 있습니다. 이번에 말하면 post 가 변수로서 사용할 수 있게 된다. 우변의 @post 는 무엇인가라고 하면, 우변의 @post 가 좌변의 post 에 대입해, 그것이 변수로서 사용할 수 있게 된다. 오른쪽의 @post는 어디에서 오는가 하면, posts 컨트롤러의 show 액션으로 정의하고 있기 때문에, 거기에서 온다.

posts_controller.rb
def show
  @post = Post.find(params[:id])
  Like.new
end

2. _like.html.hamlbutton_to path 설정
쭉 이 오류에 시달렸습니다.
ActionView::Template::Error No route matches (中略) missing required keys: [:id])

이 기사 을 찾아 마침내 아래와 같이 기술해 해결할 수 있었습니다.
= button_to 'いいねを取り消す', post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true

해결은 했지만, 이 부분 id: post.likes[0].id 하지만 아직 제대로 이해하고 있지 않습니다.
하나의 게시물에 여러 개의 좋아요가 붙어 있었는데, 그 첫번째 좋아하는 ID를 받고 있습니까?

지금 생각해 보면, 확실히 1개의 투고에 복수의 좋아하는 것이 있는 경우, 「어떤 좋아하는 것을 취소할까? 지정해 주지 않으면 모르겠어」라고 말해도 무리하지 않는 것이라고 생각했습니다.

그렇다면, 반드시 current_user의 붙이고 싶은 것이 아니라, 다른 사람의 붙이고 싶은 네를 취소해 버린다?
아직 수정해야 할 수도 있습니다 😅
(추기)
Sequel Pro에서 확인한 결과, 다른 사람의 좋아요를 취소하지 않고, 제대로 current_user의 좋아요가 취소되었습니다.

일단 좋아하는 것을 지울 수는 없어집니다.
이 점이 밝혀지면 다시 추가합니다.

참고 기사



Rails에서 remote : true와 js.erb를 사용하여 Ajax (비동기 통신)를 쉽게 구현하십시오! (좋아하는 기능의 데모 포함)
【Rails×Ajax】좋아 기능 핸즈온
Rails로 좋아하는 기능을 구현. Ajax를 사용하여 비동기 대응. 에서

좋은 웹페이지 즐겨찾기