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

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

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

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

Q&A

解決済

1回答

832閲覧

親モデルのページで表示されている子モデルのデータを、チェックボックスとボタンによって一括削除したい

kawa0tatsu

総合スコア7

Ruby on Rails

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

0グッド

0クリップ

投稿2020/04/18 16:49

前提・実現したいこと

楽曲とその音源を登録するアプリを作っています。1つの曲に対し複数の演奏音源がつきます。親モデルはpostで、子モデルはrecordingです。

button_toで楽曲ページに表示されている子モデルのデータをチェックボックスを通して一括削除したいですが、IDの指定が上手くいきません。

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

任意のrecordingのデータのチェックボックスにチェックを入れてDeleteボタンを押すとこうなります。

Couldn't find all Posts with 'id': (1, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 34, 35, 36) (found 5 results, but was looking for 21). def delete_multiple @recording = Post.find(params[:id]).recording.where(id: params[:recording_ids]) @recording.destroy_all end

該当のソースコード

rails

1 2Postモデル(親) 3 4class Post < ApplicationRecord 5 has_many :recordings, dependent: :destroy 6 has_many :post_instruments 7 accepts_nested_attributes_for :recordings, {allow_destroy: true} 8end 9 10Recordingモデル(子) 11 12class Recording < ApplicationRecord 13 belongs_to :post 14end 15 16ビュー(posts/show.html.erb) 17 18<% @post.recordings.each do |recording| %> 19  <%= check_box_tag "recording_ids[]", recording.id %> 20<% end %> 21 22<%= button_to "Delete", {action: "delete_multiple", id: @post.recording_ids,} method: :delete %> 23 24Postコントローラ 25 26 def delete_multiple 27 @post= Post.find(params[:id]).recordings.where(id: params[:recording_ids]).destroy_all 28 redirect_to('/posts/') 29 end 30 31ルーティング 32 33Rails.application.routes.draw do 34 35  resources :posts do 36    resources :recordings 37 38      collection do 39        get :'index' 40        delete :'delete_multiple' 41      end 42  end 43end 44 45 46

試したこと

指定するべきIDはあくまでrecordingモデルのIDであって、postモデルのIDではないというのは分かるのですが、そこからどうすればいいのか分かりませんでした。

Recordingコントローラにも同じようなdelete=multipleモデルを作って、button_toにおいてコントローラをcontroller: :recordingsに指定しても、使われるのはpostコントローラの方のメソッドです。

そのほかbutton=toの{}の構成などを入れ替えてたりしました。

いくつかのウェブページも参考にしました。
https://stackoverflow.com/questions/28360663/delete-multiple-records-using-checkboxes-in-rails
https://stackoverflow.com/questions/22443064/rails-destroy-multiple-record-through-check-boxes

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

rails 6.0

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

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

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

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

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

guest

回答1

0

ベストアンサー

大きな間違いが2つあります。

controllerに渡るのは PostのIDではなくRecodingのIDですから
Recording.where(id: params[:recording_ids]).destroy_all
です。

こちらは簡単なのですが。
<%= button_to "Delete",... id: @post.recording_ids,
これでは@postの全てのRecodingが削除されます。
checkしたものだけ削除ですから、
<%= check_box_tag "recording_ids[]", recording.id %>
ここの recording_ids を渡す必要があります。
それには二つの方法があります
0. button を押したら javascriptを呼んで、そこでパラメータを組み立てて送る
0. 全体を <form></form>で囲んで、buttonをsubmitにする

投稿2020/04/18 21:12

winterboum

総合スコア23349

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

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

kawa0tatsu

2020/05/01 14:02 編集

遅くなりましたがありがとうございます。 とりあえず最初の間違いについては、教えて頂くまで親モデルのコントローラでも子モデルから書き始めても良いという発想が思い浮かびませんでした。 ただ、第2の間違いについては、なぜかbutton_toからはjavascriptの関数へのonclickのイベントが発生しません。それは別の質問にしようと思います。 1と2は別々の方法ですよね?
kawa0tatsu

2020/05/01 14:07 編集

やっと出来ました・・・。結局両方の方法を使ったら望み通りの挙動になりました。 こちらhttps://teratail.com/questions/62985 のページを参考にして、公式ドキュメントのform_withの項目https://apidock.com/rails/ActionView/Helpers/FormHelper/form_withを読んでやっと解決しました。 submitボタンだとわざわざonclickを指定しなくても良いのですね。 ヒントを教えてくださりありがとうございました。 ビュー <%= form_with url: delete_multiple_posts_path, method: :delete do |f|%> (中略) <%= check_box_tag "checked_ids[]", recording.id, class: "delete" %> (中略) <%= f.submit "delete", id: "btn_submit" %> <% end %> <script language="javascript" type="text/javascript"> function call(){ var checks = document.getElementsByName("checked_ids[]"); var str = ''; for (i=0; i<checks.length; i++){ if(checks[i].checked === true){ if(str!==""){ str +=","; } str += checks[i].value; } } } </script> コントローラ def delete_multiple Recording.where(id: params[:checked_ids]).destroy_all redirect_to('/posts/') end
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問