kenichiTECHCAM
@kenichiTECHCAM

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

入力した値をDBに保存させたい。

入力した値をDBに保存させたい。

rails初心者です。
現在架空のアパレルサイトを制作しており、
その中でログインユーザーと既存のスタッフ間でチャットが出来る機能を実装しようと考えております。
新規チャット名を入力とチャットしたいスタッフ名を選んでCreate Roomボタンを押すと
以下のエラーメッセージが発生しました。
Parametersには値が入っているのでrooms_controller.rb内のparamsの記述が誤っているか、バリテーションが原因と推測していますが実際にどのような記述をして良いかわかりません。
どなたかご指導のほどよろしくお願いいたします。

発生している問題・エラー

ターミナル内
     6: def create
     7:   @room = Room.new(room_params)
 =>  8:   binding.pry
     9:   if @room.save
    10:     redirect_to root_path
    11:   else
    12:     render :new
    13:   end
    14: end

[1] pry(#<RoomsController>)> params
=> <ActionController::Parameters {"authenticity_token"=>"3J4+w9/+jQwGpE5lOioTZ52xsbuzZ41npG2NbYC9a+8rG3H01TT9Z7kB8qQv7EN377r97iN9vqGaZNKWcS2LMg==", 
"room"=><ActionController::Parameters {"name"=>"chat", "staff_name"=>"ayu", "user_id"=>"3"} permitted: false>, "commit"=>"Create Room", "controller"=>"rooms", "action"=>"create"} permitted: false>
[2] pry(#<RoomsController>)> @room.save
=> false
[3] pry(#<RoomsController>)> @room.errors
=> #<ActiveModel::Errors:0x00007f894845d7f0
 @base=
  #<Room:0x00007f894ba54ed0
   id: nil,
   name: "chat",
   user_id: 3,
   staff_name: "ayu",
   created_at: nil,
   updated_at: nil>,
 @details=
  {:staff=>[{:error=>:blank}, {:error=>:blank}],
   :user=>[{:error=>:blank}, {:error=>:blank}]},
 @messages=
  {:staff=>["must exist", "can't be blank"], :user=>["must exist", "can't be blank"]}>
[4] pry(#<RoomsController>)> 

該当するソースコード

new.html
<div class='chat-room-form'>
  <h1>新規チャットルーム</h1>
  <%=form_with model: @room, local: true do |f|%>
    <div class='chat-room-form__field'>
      <div class='chat-room-form__field--left'>
        <%= f.label :ルーム名, class: 'chat-room-form__label'%>
      </div>
      <div class='chat-room-form__field--right'>
        <%= f.text_field :name, class: 'chat__room_name chat-room-form__input', placeholder: 'ルーム名を入力してください'%>
      </div>
    </div>
    <div class='chat-room-form__field'>
      <div class='chat-room-form__field--left'>
        <label class='chat-room-form__label' for='chat_room_チャットメンバー'>スタッフ</label>
      </div>
      <div class='chat-room-form__field--right'>
        <select name="room[staff_name]">
          <option value="">チャットするスタッフを選択してください</option>
          <% Staff.all.each do |staff| %>
            <option><%= staff.staff_name %></option>
          <% end %>
        </select>
        <input name="room[user_id]" type="hidden" value=<%= current_user.id %>>
      </div>
    </div>
    <div class='chat-room-form__field'>
      <div class='chat-room-form__field--left'></div>
      <div class='chat-room-form__field--right'>
        <%= f.submit class: 'chat-room-form__action-btn'%>
      </div>
    </div>
  <% end %>
</div>
rooms_controller.rb

class RoomsController < ApplicationController
  def new
    @room = Room.new
  end

  def create
    @room = Room.new(room_params)
    binding.pry
    if @room.save
      redirect_to root_path
    else
      render :new
    end
  end

  private

  def room_params
    params.require(:room).permit(:name, :staff_name, :user_id)
  end

end
models/room.rb
class Room < ApplicationRecord
  belongs_to :staff,      foreign_key: true
  belongs_to :user,       foreign_key: true

  validates :user, presence: true
  validates :staff, presence: true
end
roomsテーブル
|id|name|user_id|staff_name|created_at|updated_at|


0

3Answer

エスパーしてみます。
テーブルとモデルの定義が合っていないのが怪しそう、と思いました。

models/room.rb には belongs_to :staff とあります。
その場合、rooms テーブルには staff_id があるのかなと思ったら無いようですし。

もし staff_name でリレーション設定する場合は以下のようにカラム名を明示的に指定する必要があります。

models/room.rb

class Room < ApplicationRecord
  belongs_to :staff,      foreign_key: :staff_name
  ...
end

foreign_key: true は model ではなく migration ファイルに書くやつだった気がします。

Active Record マイグレーション - Railsガイド

ただ、これだと同じ名前のスタッフがいたらどうするのか、などの問題があるので、リレーションはなるべくidを使った方が良いです。

ということで、Room モデルとテーブルを以下のようにしてはみるのはどうでしょうか。

models/room.rb
class Room < ApplicationRecord
  belongs_to :staff
  belongs_to :user

  validates :user, presence: true
  validates :staff, presence: true
end
roomsテーブル
|id|name|user_id|staff_id|created_at|updated_at|

フォームからは staff_name ではなく staff_id を post するように変更すれば良さそうです。

1Like

presenceblank? を呼ぶようですので,
例えば,room.user.blank? などを確認すると理由がわかるのではないか.と思いました.

0Like

Your answer might help someone💌