前提・実現したいこと
いいねボタンを非同期通信で実装したいです。
現状、ブラウザをリロードしなければアイコンの色が変化しません。
いいね機能を非同期で実装しているサイトを参考にして実装しようとしていたのですが上手くいかず、若干違うやり方をしているサイトの方法に変えてみたりしているのですが、中々改善されません。
初心者のため、jqueryやwebpackなどの設定がまだ理解できておらず、コピペに頼ってしまっているところがあるので根本的なミスも見落としがちですが、どなたかご教授いただけると助かります。
routes.rb
Rails.application.routes.draw do devise_for :users root to: 'articles#index' resources :articles do collection do get 'search' end resources :comments, only: :create resources :likes, only: [:create, :destroy] end end
#####article.rb
class Article < ApplicationRecord belongs_to :user has_many :likes def like_user(user_id) likes.find_by(user_id: user_id) end end
#####likes_controller.rb
class LikesController < ApplicationController before_action :article_params, only: [:create, :destroy] def create @like = Like.create(article_id: params[:article_id], user_id: current_user.id) end def destroy Like.find_by(article_id: params[:id], user_id: current_user.id).destroy end private def article_params @article = Article.find(params[:article_id]) end end
#####_like.html.erb
<% if user_signed_in? %> <% unless @article.like_user(current_user.id).blank? %> <%= link_to article_like_path(article_id: @article.id, id: @article.likes[0].id), method: :delete, remote: true do %> <div class="vertical_like"> <p class="like-button"><i class="fas fa-heart fa-2x" style="color: #e82a2a;"></i><span style="color: #e82a2a"><%= @article.likes.count %></span></p> </div> <% end %> <% else %> <%= link_to article_likes_path(@article.id), method: :post, remote: true do %> <div class="vertical_like"> <p class="like-button"><i class="far fa-heart fa-2x" style="color: #e82a2a;"></i><span style="color: #e82a2a"><%= @article.likes.count %></span></p> </div> <% end %> <% end %> <% end %>
create.js.erb
$('.likes_buttons').html("<%= j(render partial: 'likes/like', locals: {article: @article}) %>");
#####destroy.js.erb
$('.likes_buttons').html("<%= j(render partial: 'likes/like', locals: {article: @article}) %>");
#####application.html.erb
<!DOCTYPE html> <html> <head> <title>Stockapp</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> </head> <body class="wrapper"> <header> <%= render "shared/header" %> </header> <%= yield %> <footer> <%= render "shared/footer" %> </footer> </body> </html>
application.js
// This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application logic in // a relevant structure within app/javascript and only use these pack files to reference // that code so it'll be compiled. require('jquery'); require("@rails/ujs").start() // require("turbolinks").start() require("@rails/activestorage").start() require("channels") require("./tag") require("./preview") require("./count") require("bootstrap"); // Uncomment to copy all static images under ../images to the output folder and reference // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) // or the `imagePath` JavaScript helper below. // // const images = require.context('../images', true) // const imagePath = (name) => images(name, true) //= require bootstrap-sprockets import "bootstrap" import "../src/application.scss" import "@fortawesome/fontawesome-free/js/all"
#####environment.js
const { environment } = require('@rails/webpacker'); const webpack = require('webpack'); environment.plugins.append('Provide', new webpack.ProvidePlugin({ $: 'jquery/src/jquery', jQuery: 'jquery/src/jquery' }) ); module.exports = environment;
試したこと
jsファイルにalertを記述し、確認したところ、ちゃんと作動しました。
#####create.js.erb
$('.likes_buttons').html("<%= j(render partial: 'likes/like', locals: {article: @article}) %>"); alert('create呼ばれた!!');
#####destroy.js.erb
$('.likes_buttons').html("<%= j(render partial: 'likes/like', locals: {article: @article}) %>"); alert('destroy呼ばれた!!');
しかし連続でタップしたところ、createは連続でアラートが表示されるのですが、destroyのアラートは最初しか常時されず、2回目以降はconsoleに
rails-ujs.js:216 DELETE http://localhost:3000/articles/14/likes/11 500 (Internal Server Error)
./node_modules/@rails/ujs/lib/assets/compiled/rails-ujs.js.Rails.ajax @ rails-ujs.js:216
./node_modules/@rails/ujs/lib/assets/compiled/rails-ujs.js.Rails.handleRemote @ rails-ujs.js:652
(anonymous) @ rails-ujs.js:172
というエラーが出でしまいます。
なんとなく、AJAX通信ができていないのかな?という予想はできるのですが、そこからの対処法がわかりません。
補足情報(FW/ツールのバージョンなど)
rails 6.0.3.4
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。