【Rails×Ajax】좋아 기능의 실장으로 잘 할 수 없는 당신에게의 2개의 주의 환기 #학습자용
목적
만나서 반갑습니다.
이번, Rails에서 좋아 기능을 Qiita 등의 기사대로 가도 잘 가지 않는다! 라는 분을 향한, 약간의 실장시의 체크 항목을 열거하겠습니다.
전제 조건
대상 독자
대상 독자
개발 환경
구현된 기능
필자가 참고로 한 기사
【초보자용】 너무 정중한 Rails 『연결』 튜토리얼
Ajax 처리의 좋아하는 기능의 구현 방법의 체크 항목
앞으로 결론을 여기서 제시하겠습니다.
1. 부분 템플릿 호출이 올바르게 상대 경로로 지정되었는지
2. 인스턴스 변수 지정이 favorites_controller.rb에 지정되어 있습니까?
의 2점입니다. 그럼 자세히 살펴 보겠습니다.
1. 부분 템플릿 호출이 올바르게 상대 경로로 지정되었는지
잘 빠지기 쉬운 실수 중 하나입니다. 실제로 어떻게 실수로 구현하고 어떤 에러문이 나왔을까요?
view/items/show.html.haml.btn-bar
.btn-box
= render partial: "favorite_ajax", locals: { item: @item }
-# view/items/_favorite_ajax.html.hamlでいいねボタンを部分テンプレートを作成した
view/items/_favorite_ajax.html.haml- if user_signed_in? -# ユーザーがログインしているか判断
- if item.favorited_by?(current_user) -# ログイン中のユーザーがいいねしているかしていないかを判断
= link_to item_favorites_path(item.id), method: :delete, class: "favorite red", remote: true do -# リクエストをjs形式で送信
= icon('fas', 'heart')
いいね!
= item.favorites.count
- else
= link_to item_favorites_path(item.id), method: :post, class: "favorite", remote: true do -# リクエストをjs形式で送信
= icon('far', 'heart')
いいね!
= item.favorites.count
- else
= link_to new_user_session_path, class: "favorite", remote: false do -# リクエストをhtml形式で送信
= icon('far', 'heart')
いいね!
= item.favorites.count
view/favorites/create.js.haml(실패 예)$('.btn-box').html("#{escape_javascript(render partial: "favorite_ajax", locals: { item: @item })}");
-# この記述ではview/favorites/_favorite_ajax.html.hamlを呼び出していることとなる。従って、対応するファイルが無いことからTemplate::Error(Missing partial)が発生
view/favorites/destroy.js.haml(실패 예)$('.btn-box').html("#{escape_javascript(render partial: "favorite_ajax", locals: { item: @item })}");
-# この記述ではview/favorites/_favorite_ajax.html.hamlを呼び出していることとなる。従って、対応するファイルが無いことからTemplate::Error(Missing partial)が発生
오류 문
items_controller.rb
의 show 액션의 뷰로 좋아하는 기능의 구현을 하고 있습니다. 또, 좋아하는 기능의 DB에의 저장·삭제는 favorites_controller.rb
의 create 액션·destroy 액션으로 구현을 하고 있습니다.
이번에 좋아요 버튼을 누를 때 뷰가 전환되는 부분을 view/items/_favorite_ajax.html.haml
로 잘라내기 부분 템플릿을 만들었습니다. ajax에서는 view/favorites/create.js.haml
다음과 같이 수정하면 view/favorites/destroy.js.haml
가 해소됩니다.
view/favorites/create.js.haml$('.btn-box').html("#{escape_javascript(render partial: "items/favorite_ajax", locals: { item: @item })}");
-# partial: にitems/ を追加
view/favorites/destroy.js.haml$('.btn-box').html("#{escape_javascript(render partial: "items/favorite_ajax", locals: { item: @item })}");
-# partial: にitems/ を追加
2. 인스턴스 변수 지정이 favorities_controller.rb에 지정되어 있습니까?
여기는 먼저 어떤 오류 문장이 나왔는지 확인합시다.
render 내용 view/items/_favorite_ajax.html.haml
반대
undefined method `favorited_by?' for nil:NilClass
그리고 오류가 발생합니다. 여기서 말하는 item이란, Template::Error(Missing partial)
의 show 액션으로 정의되고 있는 인스턴스 변수 @item 를 render 의 내용에서는 item 으로서 기술하고 있다, 의 의미입니다. item.favorited_by?
에 대해서는, items_controller.rb
로 사전에 정의한 「로그인중의 유저가 좋아하는지 하고 있는지를 판단」하는 메소드입니다.
models/item.rbclass Item < ApplicationRecord
# (中略)
def favorited_by?(user)
favorites.where(user_id: user.id).exists?
end
end
이것으로부터,
render내에서는 favorited_by?
가 정의되어 있지 않다
→ render내에서는 item.rb
그 자체가 정의되어 있지 않다
→ item.favorited_by?
에서는, @item 가 정의되어 있지 않다
→ item
그럼, @item 가 정의되어 있지 않다!!
라는 것이 판명되었습니다. 확인해 보면 확실히 view/favorites/destroy.js.haml
에서는, @item 가 정의되어 있지 않았으므로, 이하와 같이 기술을 더했더니, 올바르게 Ajax 처리가 실행되었습니다.
( favorites_controller.rb
하지만 비슷한 set_item 메소드를 정의했습니다)
favorites_controller.rbclass FavoritesController < ApplicationController
before_action :authenticate_user!
# 追記==========================================================================
before_action :set_item
# ==============================================================================
def create
favorite = current_user.favorites.build(item_id: params[:item_id])
if favorite.save
else
flash.now[:alert] = favorite.errors.full_messages
end
end
def destroy
favorite = Favorite.find_by(item_id: params[:item_id], user_id: current_user.id)
if favorite.destroy
else
flash.now[:alert] = '削除できませんでした。'
end
end
private
# 追記==========================================================================
def set_item
@item = Item.find(params[:item_id])
end
# ==============================================================================
end
요약
어땠습니까?
좋아하는 기능의 Ajax는 구현 절차 자체가 매우 간단합니다. 그러나, 좋아 기능 전용의 뷰를 준비하고 있지 않거나, 부분 템플릿의 저장 장소의 차이에 의해 기술 내용이 다른 경우가 있습니다. 당연한 일입니다만, 기사대로 실장해 봐서 잘 할 수 없었을 때, 해결의 도움이 되면 다행입니다.
※나 자신 최초의 Qiita의 투고입니다!
지적 등이 있으면 코멘트에서 기다리고 있습니다.
Reference
이 문제에 관하여(【Rails×Ajax】좋아 기능의 실장으로 잘 할 수 없는 당신에게의 2개의 주의 환기 #학습자용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/shoji621/items/ab017566b6d8b9708171
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
.btn-bar
.btn-box
= render partial: "favorite_ajax", locals: { item: @item }
-# view/items/_favorite_ajax.html.hamlでいいねボタンを部分テンプレートを作成した
- if user_signed_in? -# ユーザーがログインしているか判断
- if item.favorited_by?(current_user) -# ログイン中のユーザーがいいねしているかしていないかを判断
= link_to item_favorites_path(item.id), method: :delete, class: "favorite red", remote: true do -# リクエストをjs形式で送信
= icon('fas', 'heart')
いいね!
= item.favorites.count
- else
= link_to item_favorites_path(item.id), method: :post, class: "favorite", remote: true do -# リクエストをjs形式で送信
= icon('far', 'heart')
いいね!
= item.favorites.count
- else
= link_to new_user_session_path, class: "favorite", remote: false do -# リクエストをhtml形式で送信
= icon('far', 'heart')
いいね!
= item.favorites.count
$('.btn-box').html("#{escape_javascript(render partial: "favorite_ajax", locals: { item: @item })}");
-# この記述ではview/favorites/_favorite_ajax.html.hamlを呼び出していることとなる。従って、対応するファイルが無いことからTemplate::Error(Missing partial)が発生
$('.btn-box').html("#{escape_javascript(render partial: "favorite_ajax", locals: { item: @item })}");
-# この記述ではview/favorites/_favorite_ajax.html.hamlを呼び出していることとなる。従って、対応するファイルが無いことからTemplate::Error(Missing partial)が発生
$('.btn-box').html("#{escape_javascript(render partial: "items/favorite_ajax", locals: { item: @item })}");
-# partial: にitems/ を追加
$('.btn-box').html("#{escape_javascript(render partial: "items/favorite_ajax", locals: { item: @item })}");
-# partial: にitems/ を追加
undefined method `favorited_by?' for nil:NilClass
class Item < ApplicationRecord
# (中略)
def favorited_by?(user)
favorites.where(user_id: user.id).exists?
end
end
class FavoritesController < ApplicationController
before_action :authenticate_user!
# 追記==========================================================================
before_action :set_item
# ==============================================================================
def create
favorite = current_user.favorites.build(item_id: params[:item_id])
if favorite.save
else
flash.now[:alert] = favorite.errors.full_messages
end
end
def destroy
favorite = Favorite.find_by(item_id: params[:item_id], user_id: current_user.id)
if favorite.destroy
else
flash.now[:alert] = '削除できませんでした。'
end
end
private
# 追記==========================================================================
def set_item
@item = Item.find(params[:item_id])
end
# ==============================================================================
end
어땠습니까?
좋아하는 기능의 Ajax는 구현 절차 자체가 매우 간단합니다. 그러나, 좋아 기능 전용의 뷰를 준비하고 있지 않거나, 부분 템플릿의 저장 장소의 차이에 의해 기술 내용이 다른 경우가 있습니다. 당연한 일입니다만, 기사대로 실장해 봐서 잘 할 수 없었을 때, 해결의 도움이 되면 다행입니다.
※나 자신 최초의 Qiita의 투고입니다!
지적 등이 있으면 코멘트에서 기다리고 있습니다.
Reference
이 문제에 관하여(【Rails×Ajax】좋아 기능의 실장으로 잘 할 수 없는 당신에게의 2개의 주의 환기 #학습자용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/shoji621/items/ab017566b6d8b9708171텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)