質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

995閲覧

【Ruby on Rails】いいね機能の非同期での実装で、”連続でいいねをしたい&何故かいいねボタンがたくさん出ている”を解決したい

is02

総合スコア17

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2020/01/12 08:32

編集2020/01/13 05:43

実現したいこと

・連続でいいねをしたい
・いいねボタンがたくさん出ているので1つにしたい
イメージ説明

前提

・ユーザー情報を管理する「Userモデル」
・画像投稿したり表示させるための「PostImageモデル」

発生している問題

・いいねボタンをしても反応しない
・いいねボタンがたくさん出てしまっている

該当のソースコード

####マイグレーションファイル
######favoritesテーブル(20200112070415_create_favorites.rb)

class CreateFavorites < ActiveRecord::Migration[5.2] def change create_table :favorites do |t| t.integer :user_id t.integer :post_image_id t.timestamps end end end

######post_imagesテーブル

class CreatePostImages < ActiveRecord::Migration[5.2] def change create_table :post_images do |t| t.text :real_image_name t.text :cosplay_image_name t.string :real_image_id t.string :cosplay_image_id t.text :caption t.integer :user_id t.integer :favorites_count t.timestamps end end end

######deviseユーザーテーブル

# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable # t.integer :sign_in_count, default: 0, null: false # t.datetime :current_sign_in_at # t.datetime :last_sign_in_at # t.string :current_sign_in_ip # t.string :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at t.string :name t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end end

####モデル
######favorite.rb

class Favorite < ApplicationRecord belongs_to :post_image, counter_cache: :favorites_count belongs_to :user end

######post_image.rb

class PostImage < ApplicationRecord belongs_to :user attachment :real_image attachment :cosplay_image has_many :favorites, dependent: :destroy has_many :fav_users, through: :favorites, source: :user end

######user.rb

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :post_images, dependent: :destroy validates :name, presence: true, length: { in: 2..15 } has_many :favorites, dependent: :destroy has_many :fav_post_images, through: :favorites, source: :post_image end

####ルーティング
######routes.rb

Rails.application.routes.draw do devise_for :users root 'post_images#index' resources :post_images, only: [:new, :create, :index, :show] post '/favorite/:post_image_id' => 'favorites#favorite', as: 'favorite' delete '/favorite/:post_image_id' => 'favorites#unfavorite', as: 'unfavorite' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end

####コントローラー
######favorites_controller.rb

class FavoritesController < ApplicationController before_action :set_variables def favorite favorite = current_user.favorites.new(post_image_id: @post_image.id) favorite.save end def unfavorite favorite = current_user.favorites.find_by(post_image_id: @post_image.id) favorite.destroy end private def set_variables @post_image = PostImage.find(params[:id]) @id_name = "#favorite-link-#{@post_image.id}" end end

######post_images_controller.rb

class PostImagesController < ApplicationController def new @post_image = PostImage.new end def create @post_image = PostImage.new(post_image_params) @post_image.user_id = current_user.id @post_image.save redirect_to post_images_path end def index @post_images = PostImage.all end def show @post_image = PostImage.find(params[:id]) end private def post_image_params params.require(:post_image).permit(:real_image_name, :cosplay_image_name, :real_image, :cosplay_image, :caption, :favorites_count) end end

######application_controller.rb

class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? before_action :authenticate_user! protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end end

####ビュー
######postimages/index.html.erb

<div class="header"> <nav class="navigation"> <img src="/assets/logo.png"> <ul> <li> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> </li> <li> <%= link_to '投稿する', new_post_image_path %> </li> <li> <%= link_to 'マイページ', '#' %> </li> </ul> </nav> </div> <div class="post_images_index_wrapper"> <% @post_images.each do |post_image| %> <div class="post_images_index_user"> <ul> <li><%= image_tag('no_image.jpg') %></li> <li><p><%= post_image.user.name %></p></li> </ul> </div> <div class="post_images_box"> <div class="post_image"> <%= attachment_image_tag post_image, :real_image %> </div> <div class="post_image"> <%= attachment_image_tag post_image, :cosplay_image %> </div> </div> <h3 class="block-title"> <%= link_to post_image_path(post_image.id) do %> <%= post_image.real_image_name %> <% end %> <%= link_to post_image_path(post_image.id) do %> <%= post_image.cosplay_image_name %> <% end %> </h3> <p><%= post_image.caption %></p> <a href="#">23 コメント</a> <%= render partial: 'post_images/post_images', locals: { post_image: post_image } %> <% end %> </div>

####部分テンプレート
######views/post_images/_post_images.html.erb

<%= render 'favorites/favorite', post_image: post_image %>

######views/favorites/_favorite.html.erb

<div class="favorite-link" id="favorite-link-<%= post_image.id %>"> <% if current_user.favorites.find_by(post_image_id: post_image.id) %> <%= link_to favorite_path(post_image.id), method: :post, remote: true do %> <div class = "iine__button">❤️<%= post_image.favorites.count %></div> <% end %> <% else %> <%= link_to favorite_path(post_image.id), method: :post, remote: true do %> <div class = "iine__button">♡️<%= post_image.favorites.count %></div> <% end %> <% end %> </div>

####Ajaxを使った非同期化
######views/favorites/favorite.js.erb

$("<%= @id_name %>").html('<%= escape_javascript(render("favorites/favorite", post_image: @post_image )) %>');

######views/favorites/unfavorite.js.erb

$("<%= @id_name %>").html('<%= escape_javascript(render("favorites/favorite", post_image: @post_image )) %>');

補足情報(FW/ツールのバージョンなど)

Ruby: ruby 2.5.7p206
Rails: Rails 5.2.4.1

参考サイト: [Rails]いいね機能の非同期での実装!!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

views/post_images/index.html.erb での問題でしょうか?
でしたらば、PostImagesController のcodeを載せてください。

たぶんそこで @post_images に Post.all などを入れていると思います。
partialに渡るときに post_image と単数形に変えてますが、それが混乱の元だと思います。 単数形、複数形には敏感になってください。

ただ不思議なのは post_image に @post_images が入れられているとしたら
_favorite.html.erb の <%= post_image.id %> ここでエラーになるはず。

どこか掲示するのを省略していませんか?
PostImagesController から一番下のpartialまで、関連するfileを全部、省略なしに見せてください。

追記
indexに <% @post_images.each do |post_image| %> とあり、そのloopの中で<%= render partial: 'post_images/post_images', が実行されています。
で、そのpartialから _favorite.html.erb を呼んでいいねボタンを書いてますので、@post_imagesの数、つまりユーザの数だけ いいね がでてしまいます。
良いねを一つにしたいなら <% @post_images.each do |post_image| %> のloopの外に出すのですが、、、、
でも
これ、[この人に良いね」ですよね? ですからユーザごとに出て正解では?
問題は、「この人」がわからないこと。
<%= render partial: 'post_images/post_images', collection: @post_images, as: :post_image %>にて 一人ひとり書くところで @post_images 全体を渡しているのが問題です。
<%= render partial: 'post_images/post_images', locals post_image: post_image %>としてみてください。

投稿2020/01/12 13:15

編集2020/01/12 22:20
winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

is02

2020/01/12 13:37

ご回答ありがとうございます。 views/post_images/index.html.erbでの問題です。 考えられる限りの全ての関連ファイルを追記致しました。
is02

2020/01/12 14:16

追記:いいねボタンがたくさん増える現象について いいねボタンが増える現象は、ユーザーが投稿した数だけ増えることがわかりました。 しかし、修正するところまで至っておりません。
is02

2020/01/13 05:45 編集

<%= render partial: 'post_images/post_images', locals: { post_image: post_image } %>としたことで、各ユーザーごとにいいねボタン1つのみにすることができました。 修正した部分がいくつかあります。 ・post_imagesテーブルにfavorites_countカラムの追加(favoriteモデルにbelongs_to :post_image, counter_cache: :favorites_countと書いているのにカラムが無かった為) ・post_images_controller.rbのストロングパラメータpermitにfavorites_countの追加 ・favorites_controller.rbのset_variables内 @post_image = PostImage.find(params[:post_image_id])を @post_image = PostImage.find(params[:id])に変更(これをしたら、いいねカウントをするようになりました) 現状の問題点は、 ・いいねボタンを押しても非同期でカウントされない(リロードすればカウントされる) です。 アドバイス頂けたら幸いです。
is02

2020/01/13 07:28

「いいねボタンを押しても非同期でカウントされない」を無事解決することができました。 原因はgem 'jquery-rails'が入っていなかったからでした。 未熟者の私にアドバイスを頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問