※他人のプロフィールを確認して、気になったらペアを組み、チャットできるシステムを作っています。
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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/15 10:01
2020/06/15 11:34
2020/06/16 02:45
2020/06/16 02:52
2020/06/16 03:06
2020/06/16 03:15
2020/06/16 22:00