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

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

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

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

Ruby on Rails

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Q&A

解決済

2回答

2341閲覧

中間テーブルの相手テーブルのバリデーションにより保存できない

kintarou-ryo

総合スコア3

Ruby

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

Ruby on Rails

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

0グッド

1クリップ

投稿2020/11/10 06:14

前提・実現したいこと

チャット機能のあるアプリを作成しています。
問題はroomsテーブルの保存時にusersのバリデーションにより保存できないという点です。
roomsテーブルとusersテーブルは中間テーブル(room_users)を挟んだ多対多の関係にあります。
usersの保存時には特に問題なく保存でき、バリデーションによる制限も意図した動作をしてくれます。(passwordに半角英数混合を強制させ、そのように動作します。)

usersのバリデーションを動作させた上でroomsを保存したいのですが、どのようにすれば解決できますでしょうか。ご教授お願い致します。

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

バリデーションに失敗しました: Usersは不正な値です

該当のソースコード

■views/rooms/new.html.erb

html

1<div class="contents"> 2 <div class="main"> 3 <%= render "tasks/header"%> 4 <%= form_with model:@room, local: true do |f|%> 5 <div class="center"> 6 <div class="room-builder"> 7 <div class="user-selector"> 8 <div class="user-seach"> 9 ①相談する相手を選択してください 10 </div> 11 <div class="user-scroll"> 12 <% User.all.where.not(id: current_user.id).each do |user|%> 13 <div class="user-bar" data-name=<%= user.nickname%> data-id=<%= user.id%>> 14 <%= user.nickname%> 15 </div> 16 <% end %> 17 </div> 18 </div> 19 <div class="room-form"> 20 <div class="user-confirmation" name="room[user_ids][]"> 21 ②相談する相手はこの方でよろしいですか? 22 <div class='user-confirmation-bar'> 23 </div> 24 <input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>> 25 <%# ユーザーがクリックした.user-barのdata-idをJavaScriptの操作で下記select-userのvalueにしています。 %> 26 <input name="room[user_ids][]" type="hidden" class="select-user"> 27 </div> 28 <div class="room-name"> 29 ③ルーム名を入力してください。<br> 30  何についての相談かがわかるような名前にしましょう。<br> 31  例)次の会議の予定はいつ?<br> 32 <%= f.text_field :room_name, class:'room-name-input', placeholder: 'ルーム名を入力してください'%> 33 </div> 34 <div class="instructions"> 35 ④入力が出来たら『ルーム作成』ボタンを押してルームを作成しましょう。 36 </div> 37 </div> 38 </div> 39 <% if @room.errors.any? %> 40 <div class="error-alert"> 41 <ul> 42 <% @room.errors.full_messages.each do |message| %> 43 <li class='error-message'><%= message %></li> 44 <% end %> 45 </ul> 46 </div> 47 <% end %> 48 </div> 49 <div class="footer"> 50 <%=f.submit 'ルーム作成', class:"add-task-btn" %> 51 </div> 52 <% end %> 53 </div> 54 <%= render "tasks/side"%> 55</div>

■models/user.rb

ruby

1class User < ApplicationRecord 2 # Include default devise modules. Others available are: 3 # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable 4 devise :database_authenticatable, :registerable, 5 :recoverable, :rememberable, :validatable 6 has_many :room_users, dependent: :destroy 7 has_many :rooms, through: :room_users, dependent: :destroy 8 has_many :tasks, dependent: :destroy 9 10 11 validates :nickname, presence: true, length: {in: 1..12 } 12 13 # 問題のバリデーションです。下2行をコメントアウトすると正常に保存できます。 14 PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze 15 validates_format_of :password, with: PASSWORD_REGEX, message: 'は半角英数混合で入力して下さい' 16end

■models/room.rb

ruby

1class Room < ApplicationRecord 2 has_many :room_users, dependent: :destroy 3 has_many :users, through: :room_users 4 has_many :problems, dependent: :destroy 5 6 validates :room_name, presence: true, length: {in: 1..10 } 7end

■models/room_user.rb

ruby

1class RoomUser < ApplicationRecord 2 belongs_to :user 3 belongs_to :room 4end

試したこと

①user.rbの問題のバリデーションをコメントアウト→rooms、room_users共に正常に保存可能。(勿論usersにはバリデーションがかかっていない)
②user.rbの問題のバリデーションを一意性制約に変更→rooms、room_users共に同様のエラーにより保存されず。
③バリデーションをかけた上でusersの保存→保存可能。バリデーションはpasswordを英数混合に指定する事を意図しているが、その通りに動作する。
④roomsのcreateアクションにてbinding.pryを仕込んでみる。→paramsは意図した通りのパラメーターを送っている。

From: /Users/kintarou/projects/good-question/app/controllers/rooms_controller.rb:9 RoomsController#create: 7: def create 8: @room = Room.new(room_params) => 9: binding.pry 10: if @room.save 11: redirect_to root_path 12: else 13: render :new 14: end 15: end [1] pry(#<RoomsController>)> @room => #<Room:0x00007f843bdd0330 id: nil, room_name: "次の会議の予定", created_at: nil, updated_at: nil> [2] pry(#<RoomsController>)> Started GET "/cable" for ::1 at 2020-11-10 14:42:27 +0900 [2] pry(#<RoomsController>)> params => <ActionController::Parameters {"authenticity_token"=>"lqTqiP2G7lc/kKrguWt7DrNNPPYgsAcX4ISbx/kvFe51zWC+PUvWDr6TOdDTn9HHphM1zm1eAQxrvS5gHKXaKQ==", "room"=><ActionController::Parameters {"user_ids"=>["1", "2"], "room_name"=>"次の会議の予定"} permitted: false>, "commit"=>"ルーム作成", "controller"=>"rooms", "action"=>"create"} permitted: false> [3] pry(#<RoomsController>)> @room.save! ActiveRecord::RecordInvalid: バリデーションに失敗しました: Usersは不正な値です from /Users/kintarou/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.3/lib/active_record/validations.rb:80:in `raise_validation_error' [4] pry(#<RoomsController>)>

⑤サーバー再起動・PC再起動→状況変わらず。

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

Rails 6.0.3.3
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]

初めての質問で要領を得ない事、足りない情報あるかもしれませんが、ご容赦ください。
併せてご教授頂ければ幸いです。
よろしくお願い致します。

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

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

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

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

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

guest

回答2

0

ベストアンサー

よくわかっていないので、ちょっと調べた程度の回答です。

バリデーションで困っているなら、belongs_to :user, validate: falseで回避できそうな気がしました。(API dock: belongs_to

:validate
When set to true, validates new objects added to association when saving the parent object. false by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.

ただvalidate:falsedefaultなので。。。どうなんだろう

投稿2020/11/10 07:47

no1knows

総合スコア3365

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

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

kintarou-ryo

2020/11/10 10:06

■models/room.rb has_many :users, through: ;room_users, validate: false とすることで保存可能になりました!ありがとうございます! 私自身他テーブルのバリデーションは何も操作しなければ無関係という認識だったので、どこでusersのバリデーションがかかることになったのかは不明です。 もっと知識をつけようと思います。
no1knows

2020/11/10 10:33

たしかに中間テーブルで他のテーブルのバリデーションが引っかかるのは変な気がしますね。。。 なにはともあれ解決してよかったです!
guest

0

bin/rails consoleを起動して以下のコードを実行したら、保存できますか?

ruby

1user_ids = [1, 2] 2room = Room.new(room_name: "次の会議の予定") 3room.users << User.where(id: user_ids) 4room.save!

これで保存できるようであれば、このように書き換えたらうまくいくかもしれません。
上記のコードが動かない場合はこちらの予測が外れているので忘れてください。

ruby

1def create 2 user_ids = params[:room][:user_ids] # => ["1", "2"] 3 4 @room = Room.new(room_params) 5 @room.users << User.where(id: user_ids) 6 7 if @room.save 8 redirect_to root_path 9 else 10 render :new 11 end 12end

投稿2020/11/10 07:00

mingos

総合スコア4025

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

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

kintarou-ryo

2020/11/10 07:23

早速のご回答ありがとうございます! 以下、試してみました。 ``` From: /Users/kintarou/projects/good-question/app/controllers/rooms_controller.rb:8 RoomsController#create: 7: def create => 8: binding.pry 9: @room = Room.new(room_params) 10: if @room.save 11: redirect_to root_path 12: else 13: render :new 14: end 15: end [1] pry(#<RoomsController>)> user_ids = [1,2] => [1, 2] [2] pry(#<RoomsController>)> room = Room.new(room_name: "次の会議の予定") => #<Room:0x00007f8446254488 id: nil, room_name: "次の会議の予定", created_at: nil, updated_at: nil> [3] pry(#<RoomsController>)> room.users << User.where(id: user_ids) User Load (1.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2) ↳ (pry):6:in `create' => [#<User id: 1, nickname: "太郎", email: "test@test.com", created_at: "2020-10-29 08:34:09", updated_at: "2020-10-29 08:34:09", phone_number: "09099999999">, #<User id: 2, nickname: "次郎", email: "test2@test.com", created_at: "2020-10-29 08:34:37", updated_at: "2020-10-29 08:34:37", phone_number: "09099999999">] [4] pry(#<RoomsController>)> room.save! ActiveRecord::RecordInvalid: バリデーションに失敗しました: Usersは不正な値です from /Users/kintarou/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.3/lib/active_record/validations.rb:80:in `raise_validation_error' [5] pry(#<RoomsController>)> ``` 一度コードを変えてみましたがやはり「Usersは不正な値です」となります。 一度も試してない方法だったので参考になります。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問