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

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

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

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

Ruby

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

1回答

1403閲覧

collection_check_boxesも使用して、中間テーブルにデータを保存できるようにしたいです。

RYtera

総合スコア8

Ruby on Rails 5

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

Ruby

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2020/06/14 02:47


※他人のプロフィールを確認して、気になったらペアを組み、チャットできるシステムを作っています。

collection_check_boxesを使用して、中間テーブルへデータを保存しようとする際に、Rollbackが起こりデータが反映されない状況です。

※アプリの遷移イメージ
(プロフィール確認画面)abouts#show
→ (ペア選択作成画面)pairs#new
→ (ペア個別のチャット画面)messages#indexかmessage#showのどちらか

※ペア選択画面
collection_check_boxesでペアを選択して、送信ボタンを押下時に、エラーが発生します。
https://gyazo.com/863a5ff424022d7b1859c56a4ec01d59

※pairsテーブルとusersテーブルで多対多のため、users_pairsテーブルを中間テーブルとして作成しています。
usersはdeviseというgemを用いています。

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

※言語はRuby/Railsを使用しています。 #ターミナル(「ROLLBACK」の発生画面です。) Started POST "/pairs" for ::1 at 2020-06-14 10:00:10 +0900 Processing by PairsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"n2zXfeafIUSRIRHQOId5NK/vwaPQPYp6yIpHuTKFniJRGDqM3gw/Zi22LsPmKp1/dNfOQbWkxgWnVWZMwImPaQ==", "pair"=>{"name"=>"test", "user_ids"=>["", "6", "7"]}, "commit"=>"送信"} User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 ORDER BY `users`.`id` ASC LIMIT 1 ↳ /Users/ryootani/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/log_subscriber.rb:98 User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (6, 7) ↳ app/controllers/pairs_controller.rb:15 (0.2ms) BEGIN ↳ app/controllers/pairs_controller.rb:16 User Exists (0.6ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'dddd@dddd' AND `users`.`id` != 6 LIMIT 1 ↳ app/controllers/pairs_controller.rb:16 User Exists (0.5ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'eeee@eeee' AND `users`.`id` != 7 LIMIT 1 ↳ app/controllers/pairs_controller.rb:16 Pair Exists (0.3ms) SELECT 1 AS one FROM `pairs` WHERE `pairs`.`name` = BINARY 'test' LIMIT 1 ↳ app/controllers/pairs_controller.rb:16 (0.3ms) **ROLLBACK** ↳ app/controllers/pairs_controller.rb:16 Rendering pairs/new.html.haml within layouts/application User Load (0.3ms) SELECT `users`.* FROM `users` ↳ app/views/pairs/new.html.haml:37 Rendered pairs/new.html.haml within layouts/application (24.0ms) Rendered maps/_header.html.haml (6.5ms) Rendered maps/_footer.html.haml (5.4ms) Completed 200 OK in 151ms (Views: 117.2ms | ActiveRecord: 3.0ms)

ソースコードと試したこと

ターミナルのエラー文Parametersから、collection_check_boxesで情報の取得はできていそうです。
何らかの理由でデータベースへの保存ができていないのでは考えています。

1. バリデーションを下記のように見直しました。 (has_many xx through xx や、belongs_to optionalの追記、記載順など) #pair.rb class Pair < ApplicationRecord has_many :users_pairs has_many :users, through: :users_pairs accepts_nested_attributes_for :users_pairs, allow_destroy: true validates :name, presence: true, uniqueness: true has_many :messages, dependent: :destroy accepts_nested_attributes_for :messages, allow_destroy: true end #users_pair.rb class UsersPair < ApplicationRecord belongs_to :pair,optional: true belongs_to :user,optional: true end #user.rb class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable # 1ユーザ1プロフィールのため has_one :about # 半角英数字、大小文字、8文字以上 VALID_NAME_PW_REGEX = /\A^([a-zA-Z0-9]{8,})$\z/i validates :name, presence: true, format: { with: VALID_NAME_PW_REGEX } # 半角英数字、大小文字、数字、ドットを少なくとも1つ以上繰り返す。@を挟む VALID_EMAIL_REGEX = /\A[a-zA-Z\d.]+@[a-zA-Z\d.]+\z/i validates :email, presence: true, uniqueness: { case_sensitive: false }, format: { with: VALID_EMAIL_REGEX } validates :password, presence: true, format: { with: VALID_NAME_PW_REGEX } has_many :users_pairs, dependent: :destroy has_many :pairs, through: :users_pairs accepts_nested_attributes_for :users_pairs, allow_destroy: true has_many :messages, dependent: :destroy accepts_nested_attributes_for :messages, allow_destroy: true end 2. null: falseが原因と考え、users_pairsマイグレーションファイルの、 null:falseを削除しました。 #pair class CreatePairs < ActiveRecord::Migration[5.2] def change create_table :pairs do |t| t.string :name, null: false t.index :name, unique: true t.timestamps end end end #users_pairs class CreateUsersPairs < ActiveRecord::Migration[5.2] def change create_table :users_pairs do |t| t.references :user, foreign_key: true t.references :pair, foreign_key: true t.timestamps end end end 3. ビュー画面とコントローラーです。 #app/views/pairs/new.html.haml Knock on the door? About ME:わたしの名前とid番号 = current_user.name = current_user.id ーーーーーーーーー check a door knob ,and Knock-knock! = form_for @pair do |f| = f.text_field :name, class: "chatGroup__input", placeholder: "ペア名を入力してください" = f.collection_check_boxes :user_ids, User.all, :id, :name = f.submit "送信", class: "chatGroup__btn" #app/controllers/pairs_controller.rb class PairsController < ApplicationController def new @pair = Pair.new @pair.users << current_user @about = About.find_by(id: params[:format]) end def create binding.pry @pair = Pair.new(pair_params) if @pair.save redirect_to root_path else render :new end end private def pair_params params.require(:pair).permit(:name, user_ids: []) end end 4. ストロングパラメータが理由と考え、コントローラーのuser_ids:[]を外してみました pairsテーブルへの登録は可能です。 users_pairsテーブルへは登録不可でした。 5. 4より中間テーブルへの保存が怪しいと考え、直接保存を試みたところ、詰まりました。 %console c よりcreateメソッドするも保存出来なかったため、newとsaveに分けて試しました。 saveでエラーが出たためエラー内容を確認しました。 ※ターミナル画面の画像も貼ります。 https://gyazo.com/f2ec939a55a3008f2752c78a3892d29d -------------------------------------------------- Running via Spring preloader in process 1049 Loading development environment (Rails 5.2.4.3) [1] pry(main)> pair = Pair.new(name: "中間テーブルテスト", user_ids: [6,7]) (0.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (6, 7) => #<Pair:0x00007f9322c1b4e0 id: nil, name: "中間テーブルテスト", created_at: nil, updated_at: nil> [2] pry(main)> pair.save! (0.2ms) BEGIN User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'dddd@dddd' AND `users`.`id` != 6 LIMIT 1 User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'eeee@eeee' AND `users`.`id` != 7 LIMIT 1 Pair Exists (0.3ms) SELECT 1 AS one FROM `pairs` WHERE `pairs`.`name` = BINARY '中間テーブルテスト' LIMIT 1 (0.2ms) ROLLBACK ActiveRecord::RecordInvalid: Validation failed: Users is invalid from /Users/ryootani/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/validations.rb:80:in `raise_validation_error' [3] pry(main)> pair.errors => #<ActiveModel::Errors:0x00007f931ef0c770 @base=#<Pair:0x00007f9322c1b4e0 id: nil, name: "中間テーブルテスト", created_at: nil, updated_at: nil>, @details={:users=>[{:error=>:invalid}, {:error=>:invalid}]}, @messages={:users=>["is invalid"]}> [4] pry(main)> pair.valid? User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'dddd@dddd' AND `users`.`id` != 6 LIMIT 1 User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'eeee@eeee' AND `users`.`id` != 7 LIMIT 1 Pair Exists (0.4ms) SELECT 1 AS one FROM `pairs` WHERE `pairs`.`name` = BINARY '中間テーブルテスト' LIMIT 1 => false [5] pry(main)> pair.invalid? User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'dddd@dddd' AND `users`.`id` != 6 LIMIT 1 User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'eeee@eeee' AND `users`.`id` != 7 LIMIT 1 Pair Exists (0.4ms) SELECT 1 AS one FROM `pairs` WHERE `pairs`.`name` = BINARY '中間テーブルテスト' LIMIT 1 => true [6] pry(main)> pair.errors[:users] => ["is invalid"] [7] pry(main)> pair.errors.messages => {:users=>["is invalid"]} [8] pry(main)> pair.errors.details => {:users=>[{:error=>:invalid}, {:error=>:invalid}]} [9] pry(main)> --------------------------------------------------
6. 5よりpairs#createの「@pair = Pair.new(pair_params)」に注目しpryを試しました。 > pair_params > => <ActionController::Parameters {"name"=>"test", "user_ids"=>["", "6", "7"]} permitted: true> > Pair.new(pair_params) > => #<Pair:0x00007fe6a24887e0 id: nil, name: "test", created_at: nil, updated_at: nil> > @pair > => nil 7. raise_validation_error ターミナルで上記があり、リファレンスを探しましたが 有効な情報にヒットしませんでした。 以上、 5と6から、 「変数が上手く渡せていない」か「バリデーション」が原因と考えていますが、 どう修正すれば保存できるようになるのかわかっておりません。

原因が分からずほんの少しのヒントやアイデアでも頂けますと幸いです。
よろしくお願いいたします。

補足情報

Rails 5.2.4.3
ruby 2.5.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

pair = Pair.new(name: "中間テーブルテスト", user_ids: [6,7])
user_ids: [6,7] がよろしくないです。

pair = Pair.new(name: "中間テーブルテスト" pair.users = User.where(id: [6,7])
かな

投稿2020/06/14 14:38

winterboum

総合スコア23284

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

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

RYtera

2020/06/15 10:01

ご回答ありがとうございます! ターミナルから直接データベースへ保存を行う場合、 winterboum様にアドバイス頂いた方法で成功しました! 一方でエディターへの記載方法について分からずにいます。 pair.usersを分けるという目的で、 エディターへ下記等の修正をしてみましたが 同じようにsave出来ずにいます(Rollbackの状況です)。 ``` #試行例1:app/controllers/pairs_controller.rb#newの修正 def new @pair = Pair.new(:name) @pair.users = User.where(params[:id]) @about = About.find_by(id: params[:format]) end #試行例2;app/controllers/pairs_controller.rb#createとストロングパラメータの修正 def create @pair = Pair.new(pair_params) @pair.save @pair.users = User.where(user_params) @pair.users.save end private def pair_params params.require(:pair).permit(:name) end def user_params params.require(:pair).permit(user_ids:[]) end ``` もう少しで保存できるのかも知れませんが解決出来ずにいます。 大変お手数ですがアドバイス頂けますと幸いです。
winterboum

2020/06/15 11:34

@pair.users = User.where(user_params) を @pair.users = User.where(params[:user_ids]) に このあとのsaveは不要です。
RYtera

2020/06/16 02:45

頂いた下記修正案にて検証試してみました。 ``` #app/controllers/pairs_controller.rb def create @pair = Pair.new(pair_params) @pair.save @pair.users = User.where(params[:user_ids]) end private def pair_params params.require(:pair).permit(:name) end ``` 結果としては、 pairsテーブルとusers_pairsテーブルへの保存はできるものの collection_check_boxesのチェック有無に関わらず、 全ユーザが保存されてしまう状況です。 ※参考:pair名:test38、ユーザー名:dddddddさんとeeeeeeeさんを選択、 して送信ボタンを押下の場合 https://gyazo.com/94566e4be5092cd8c4bdbf281d23e5d9 > pairsテーブルにINSERTで保存され > JOINでテーブル結合 > users_pairsテーブルにINSERTで全ユーザのデータが保存されています。 > ※collection_check_boxesで選択したのは、2ユーザのみでした。 そこでparams[:user_ids]でデータを拾えてきていないと考え 、 下記にして検証したところ、同様に、全ユーザのデータが保存されてしまいました。(数値10に置き換えて検証) ``` #app/controllers/pairs_controller.rb def create @pair = Pair.new(pair_params) @pair.save @pair.users = User.where(params[10]) end ``` collection_check_boxesの文法を疑い、リファレンスを再度見直しましたが問題なさそうです。(form_forの場合第一引数省略可) ``` #app/views/pairs.new.htnl.haml = form_for @pair do |f| = f.text_field :name, class: "chatGroup__input", placeholder: "ペア名を入力してください" = f.collection_check_boxes :user_ids, User.all, :id, :name = f.submit "送信", class: "chatGroup__btn" ``` 現状にて、pairs#createの真下でpryを試してみました。 ``` #app/controllers/pairs_controller.rb def create binding.pry @pair = Pair.new(pair_params) @pair.save @pair.users = User.where(params[:user_ids]) end private def pair_params params.require(:pair).permit(:name) end =>[1] pry(#<PairsController>)> params => <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"Pf+V75yE3VEwOj86Sb/fYZR2G3oS85n6NPxZfLMEcO3zi3gepBfDc4ytACmXEjsqT04UmHdq1YVbI3iJQQhhpg==", "pair"=>{"name"=>"test42", "user_ids"=>["", "6", "7"]}, "commit"=>"送信", "controller"=>"pairs", "action"=>"create"} permitted: false> ``` pry > params を試してみると、 "user_ids"=>["", "6", "7"]、が取得できていそうなのですが、 テーブルに保存されるデータと異なっており考えあぐねています。。
winterboum

2020/06/16 03:15

よく見ると、 @pair.users = User.where(params[:user_ids]) ですね @pair.users = User.where(id: params[:user_ids]) です
RYtera

2020/06/16 22:00

winterboum様 アドバイスありがとうございます。 下記を元に検証を重ね、 何とかcollection_check_boxesのデータを反映する事ができました! > @pair.users = User.where(id: params[:user_ids]) 本当にありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問