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

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

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

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

Ruby on Rails

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

Q&A

解決済

2回答

1636閲覧

railsでいいね機能のボタンの共通化がしたいが一覧ページでエラーがでる

p-plus

総合スコア43

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2019/08/22 18:04

編集2019/08/23 12:57

前提・実現したいこと

ruby on railsでユーザーが、ゲームのリストからいいね!する機能を一覧ページと
ゲームの個別ページでパーシャル化したい。
個別ページでは問題なく動きます。

おかげさまで解決しました(該当部分のみ)

resourcesからresourceに変更

routes

1 resources :games, only: [:index, :show, :create, :destroy] do 2 resource :wants, only: [:create, :destroy] 3 end

すると↓が「game_want_pathじゃなくてgame_wants_pathじゃない?」というエラーが出たので、wantsにしたところ、エラーは出なくなりました
パーシャル化したファイル(app/views/wants/_want.html.erb)

<% if current_user.already_wanted?(@game) %> <%= button_to 'いいねを取り消す', game_want_path(@game), method: :delete %> <% else %> <%= button_to 'いいね', game_wants_path(@game) %> <% end %>

ですが、一つのゲームがループして出力されるごとにすべてのゲームのいいねボタンがでるようになってしまいましたので
以下のようにかきかえました
エラーが出るゲーム一覧ページ(app/views/games/index.html.erb)

<% if @games.any? %> <ul class="list-unstyled"> <% @games.each do |game| %> <li class="media"> <div class="media-body"> <div> <%= link_to game_path(game) do %> <%= image_tag game.image.to_s %> <%= game.game_name %></p> <% end %> <% @game = game %> <div><%= render partial: 'wants/want' ,games: @games %></div> </div> </div> </li> <% end %> </ul> <% end %>

これで動くようになりました

発生している問題・エラーメッセージ

エラーメッセージ ActionController::UrlGenerationError in Games#index Showing /home/ec2-user/environment/game-friends/app/views/wants/_want.html.erb where line #4 raised: No route matches {:action=>"create", :controller=>"wants", :game_id=>nil}, missing required keys: [:game_id]

該当のソースコード

routes

1Rails.application.routes.draw do 2 # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html 3 root to: 'toppages#index' 4 5 get 'login', to: 'sessions#new' 6 post 'login', to: 'sessions#create' 7 delete 'logout', to: 'sessions#destroy' 8 9 get 'signup', to: 'users#new' 10 get 'games/new', to: 'games#new' 11 resources :users, only: [:index, :show, :new, :create] do 12 member do 13 get :wants 14 end 15 end 16 17 resources :games, only: [:index, :show, :create, :destroy] do 18 resources :wants, only: [:create, :destroy] 19 end 20 21 22end 23 24

パーシャル化したファイル(app/views/wants/_want.html.erb)

<% if current_user.already_wanted?(@game) %> <%= button_to 'いいねを取り消す', game_want_path(@game), method: :delete %> <% else %> <%= button_to 'いいね', game_wants_path(@game) %> <% end %>

エラーが出るゲーム一覧ページ(app/views/games/index.html.erb)

<% if @games.any? %> <ul class="list-unstyled"> <% @games.each do |game| %> <li class="media"> <div class="media-body"> <div> <%= link_to game_path(game) do %> <%= image_tag game.image.to_s %> <%= game.game_name %></p> <% end %> <div><%= render partial: 'wants/want' ,games: @games %></div> </div> </div> </li> <% end %> </ul> <% end %>

app/controllers/wants_controller.rb

class WantsController < ApplicationController before_action :require_user_logged_in def create @game = Game.find(params[:game_id]) @wants = Want.new( game_id: params[:game_id], user_id: current_user.id ) if @wants.save redirect_to game_path(@game) else render template: 'games/show' end end def destroy @wants = Want.find_by(user_id: current_user.id, game_id: params[:game_id]) if @wants.destroy flash[:success] = "いいね解除しました" redirect_to "/games/#{params[:game_id]}" end end private def wants_params params.require(:wants).permit(:game_id, :user_id) end end

app/controllers/games_controller.rb

class GamesController < ApplicationController before_action :require_user_logged_in before_action :correct_user, only: [:destroy] before_action :admin_user, only: [:new] def index @games = Game.all @game = Game.new end def show @game = Game.find(params[:id]) @game_regist = Game.new @wants = Want.new end def create @game = Game.new(game_params) if @game.save flash[:success] = 'gameが正常に投稿されました' redirect_back(fallback_location: root_path) else flash.now[:danger] = 'gameが投稿されませんでした' redirect_back(fallback_location: root_path) end end def new @game = Game.new end def edit @game = Game.find(params[:id]) end def update @game = Game.find(params[:id]) if @game.update(game_params) flash[:success] = 'Gameは正常に更新されました' redirect_to @game else flash.now[:danger] = 'Gameは更新されませんでした' render :edit end end def destroy @game = Game.find(params[:id]) if @game.destroy flash[:success] = "ゲーム削除しました" redirect_to "/games/" end end private # Strong Parameter def game_params params.require(:game).permit(:game_name, :image) end def correct_user @game = Game.find(params[:id]) unless @game redirect_to root_url end end def admin_user redirect_to(root_url) unless current_user.admin? end end

app/controllers/users_controller.rb

class UsersController < ApplicationController before_action :require_user_logged_in, only: [:index, :show] def index @users = User.order(id: :desc).page(params[:page]).per(25) end def new @user = User.new end def show @user = User.find(params[:id]) likescounts(@user) end def create @user = User.new(user_params) if @user.save flash[:success] = 'ユーザを登録しました。' redirect_to @user else flash.now[:danger] = 'ユーザの登録に失敗しました。' render :new end end def likes @user = User.find(params[:id]) @favoritings = @user.favoritings.page(params[:micropost]) counts(@user) likescounts(@user) end private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation, :gender, :thumbnail, :introduction) end end

ご指摘をいただいて編集したところ(app/views/games/index.html.erb)

<% if @games.any? %> <ul class="list-unstyled"> <% @games.each do |game| %> <li class="media"> <div class="media-body"> <div> <%= link_to game_path(game) do %> <%= image_tag game.image.to_s %> <%= game.game_name %></p> <% end %> <% @games.each do |game| %> <% @game = game %> <div><%= render partial: 'wants/want' ,games: @games %></div> <% end %> </div> </div> </li> <% end %> </ul> <% end %>

もしかしてroutes.rbのここが悪いのでは?と思ったところ

resources :games, only: [:index, :show, :create, :destroy] do resources :wants, only: [:create, :destroy] end

試したこと

>game_id=>nilこれが問題であるのはわかるのですが・・・

https://qiita.com/nojinoji/items/2c66499848d882c31ffa
https://qiita.com/koooosk31/items/bb74146ea3d8339e35d6
https://tamiz-blog.com/programming/rails20190706/
このあたりを参考にしたりして1からやりなおしてみたりしたのですが、
どうしても解決できませんでした。

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

データベースとしてはusersとgamesの間にwantsという中間テーブルでつないでいる状態です。
お手数おかけしますがよろしくおねがいいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

利用側:

<div><%= render partial: 'wants/want' ,games: @games %></div>

erb

1<div><%= render partial: 'wants/want', locals: game: game %></div>

もしくは、省略形の

erb

1<div><%= render 'wants/want', game: game %></div>

partial側:

erb

1 <% if current_user.already_wanted?(game) %> 2 <%= button_to 'いいねを取り消す', game_want_path(game), method: :delete %> 3 <% else %> 4 <%= button_to 'いいね', game_wants_path(game) %> 5 <% end %>

インスタンス変数は使わない

投稿2019/08/22 22:36

asm

総合スコア15147

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

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

p-plus

2019/08/23 01:57

ありがとうございます! お二人にご回答いただいたのですが、それをふまえて反映したところ 同じエラー文になりましたのでもうひとりの方のほうに返答させていただきました。
asm

2019/08/23 03:10

> resources :wants, only: [:create, :destroy] ここが悪いですね。 resource :wants, only: [:create, :destroy] にする事で改善する可能性があります。 resourcesのdestroyは特定ユーザーの"呟き"のようにたくさんあるものから選んで消す必要があるのでidが必要になります。
p-plus

2019/08/23 03:24

ご回答ありがとうございます! こちら修正しましたところ、以下のところで「game_want_pathじゃなくてgame_wants_pathじゃない?」というエラーが出たので、wantsにしたところ、エラーは出なくなりましたがいいねボタンが 一つのゲームがループして出力されるごとにすべてのゲームのいいねボタンがでるようになってしまいました・・・(今4件ゲームが登録されているので1画面に計16個) いいねボタン自体は機能しているようです! https://gyazo.com/7bb8e651696d14a4d6682d453ceca1d5 <%= button_to 'いいねを取り消す', game_want_path(@game), method: :delete %> ↓ <%= button_to 'いいねを取り消す', game_wants_path(@game), method: :delete %>
asm

2019/08/23 03:30

<% @games.each do |game| %>のなかに<% @games.each do |game| %>があれば そりゃ、そうなる としか言いようがないです
p-plus

2019/08/23 03:38

<% @game = game %> これだけ残したら希望通りできました!!!!! くりかえしの中にくりかえし書いてたからそうなってたんですね! やったーありがとうございます! 落ち着いたらちゃんとまとめますので一旦解決済とさせていただきます! ありがとうございました!
guest

0

partialでは @game を使っているのに、一覧では @game がないからです。

個別で
render partial: 'wants/want' ,game: @game
一覧で
render partial: 'wants/want' ,game: game
としてpartial側では @geme を game にする


あまりやりたくはないですが一覧で
<% @games.each do |game| %>
<% @game = game %>
としてごまかすか

投稿2019/08/22 22:33

winterboum

総合スコア23329

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

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

p-plus

2019/08/23 01:56

ありがとうございます! index.html.erb内のpartialの呼び出しを以下コードで囲ってみると 以下のようにエラー文が変わりました! No route matches {:action=>"destroy", :controller=>"wants", :game_id=>#<Game id: 1, game_name: "aeee", image: "slider05.png", created_at: "2019-08-21 17:29:14", updated_at: "2019-08-21 17:29:14">}, missing required keys: [:id] もう一件頂いた回答のほうも同じエラーになりました。 game_idがうまくとれてきていないということでしょうか
winterboum

2019/08/23 02:08

:action=>"destroy" はタダ事ではないですね。 form の行も含むように index.html のviewの開示を増やして下さい
p-plus

2019/08/23 02:24

編集したindex.html.erb追記させていただきました。
winterboum

2019/08/23 02:35

<%= button_to 'いいねを取り消す', game_want_path(@game), method: :delete %> を押してます? game_want_path(@game) @game を game_want_path(id: @game.id) にすればとりあえず通ると思いますが、、、 なんか気持ち悪いな。個別では通ったんですね?
p-plus

2019/08/23 02:51

説明不足で申し訳ありません。 ボタンを押す以前に一覧ページが表示できない状態です /games/ でエラーが出ていて /games/1 などのゲームの個別ページではボタンが動作するという状況です。
p-plus

2019/08/23 03:39

winterboumさん たびたび申し訳ありません、おかげさまで問題解決しました! 何度も何度も質問してしまいお時間つかっていただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問