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

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

ただいまの
回答率

87.78%

中間テーブルを用いたデータの保存について

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 315

score 1

閲覧して頂き、ありがとうございます。

かなり長文になってしまいましたが、ご確認頂き、アドバイス頂けますと幸いです。

よろしくお願い致します。

実現したい機能とデータベース設計

mixiのコミュニティ(当アプリではgroup)のような機能のアプリを作成しております。

そのためにはデータベース設計として、

groupテーブル
userテーブル
中間テーブルとしてgroup_users

が必要であると考えました。

保存の手順としては、

手順1.ログインしたユーザーはgroupを作成でき、作成されるとgroupテーブルにgroupの情報が保存され、中間テーブルであるgroup_usersテーブルに作成されたgroupのidと作成したuserのidが保存される。(views/groups/new.html.erbのgroup作成フォーム)

手順2.作成されたグループに新たなユーザーが参加した際は、中間テーブルであるgroup_usersテーブルに参加したgroupのidと参加したuserのidが保存される。(views/groups/index.html.erbのgroup参加フォーム)

という二段階のデータベース設計が必要かと考えました。

mixiのコミュニティのような機能を作成する際はこのようなデータベース設計、フォームの実装で方向性は間違っていませんでしょうか?

現状の実装とエラーについて

現状は、

1.groupモデル、userモデル、group_usersテーブルの実装
2.groupコントローラー、userコントローラーの実装
3.deviseの実装
4.ルーティングの設定
5.viewの実装とformの作成
6.groupコントローラーの編集を行いました。

上記の手順で実装を行いました。

ですが、データベース設計の手順1.の部分の作成されたgroupのデータはgroupテーブルに保存は出来ていましたが、中間テーブルにはgroup_idとuser_idが保存されない状態でした。

※下記classについては過去に作成したアプリから引用しておりますので、ズレているところがあります。

groupテーブルのみ保存された時のコントローラーとview

#GroupsController
class GroupsController < ApplicationController

  def new
    @group = Group.new
  end

  def index
    @groups = Group.all
    @groups = Group.order("created_at DESC")
  end

  def create
    @group = Group.new(group_params)
    if @group.save
      redirect_to root_path
    else
      render :new
    end
  end

  private

    def group_params
      params.require(:group).permit(:name, :text, :category_id, :genre_id, :image, {user_id: []} )
    end

end
#views/groups/new.html.erb

<div class='chat-room-form'>
  <h1>新規グループ作成</h1>
  <%=form_with model: @group, local: true do |f|%>

      <%# user_idを送るための記述 %>
        <div class='group-room-form__field--left'>
        <%= f.label :メンバー, class: 'group-room-form__label'%>
      </div>
      <div class='group-room-form__field--right'>
        <%= text_field_tag 'group[user_id]', current_user.id %>
      </div>
      <%# //user_idを送るための記述 %>

    <div class='group-form__field'>
      <div class='group-room-form__field--left'>
        <%= f.label :グループ名, class: 'group-room-form__label'%>
      </div>
      <div class='group-room-form__field--right'>
        <%= f.text_field :name, class: 'group__room_name group-room-form__input', placeholder: 'グループ名を入力してください'%>
      </div>
      <div class="group-room-form__field--left">
        <%= f.label :image, "グループアイコン" %><br />
        <%= f.file_field :image %>
      </div>
      <div class='group-room-form__field--left'>
        <%= f.label :カテゴリー, class: 'group-room-form__label'%>
      </div>
      <div class='group-room-form__field--right'>
        <%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"group-select"}) %>
      </div>
      <div class='group-room-form__field--left'>
        <%= f.label :ジャンル, class: 'group-room-form__label'%>
      </div>
      <div class='group-room-form__field--right'>
        <%= f.collection_select(:genre_id, Genre.all, :id, :name, {}, {class:"group-select"}) %>
      </div>
      <div class='group-room-form__field--left'>
        <%= f.label :グループ説明, class: 'group-room-form__label'%>
      </div>
      <div class='group-room-form__field--right'>
        <%= f.text_field :text, class: 'group__room_name group-room-form__input', placeholder: 'どんなグループ?'%>
      </div>
    </div>
    <div class='group-form__field'>
      <div class='group-form__field--left'></div>
      <div class='group-form__field--right'>
        <%= f.submit class: 'group-form__action-btn'%>
      </div>
    </div>
  <% end %>
</div>

user_idを送る記述がおかしいと思い、user_idを送るための記述を下記のように記述したらgroupも保存されませんでした。
<div class='chat-room-form__field--right'>         <input name="[user_ids][]" type="hidden" value=<%= current_user.id %>>       </div>

また、これ以外にも様々試みましたが、いずれも保存は出来ず、use_idが取得出来ませんでした。

そもそものデーターベース設計、または、送るデータの記述が間違っているのでしょうか?

アドバイス頂けましたら幸いです。

その他の関連するコード

#GroupModel

class Group < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions

  belongs_to :category
  belongs_to :genre

  has_many :group_users
  has_many :users, through: :group_users, dependent: :destroy
  # accepts_nested_attributes_for :group_users
  has_many :messages, dependent: :destroy

  has_one_attached :image

  with_options presence: true do
    validates :name, uniqueness: true
    validates :text
    validates :category_id
    validates :genre_id
  end

  with_options numericality:{other_than: 1} do
    validates :category_id
    validates :genre_id
  end

end
#UserModel

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable



  validates :nickname,         presence: true
  validates :password,         presence: true
  PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
  validates_format_of :password, with: PASSWORD_REGEX 
  with_options presence: true, format: { with: /\A[ぁ-んァ-ン一-龥]+\z/} do
  validates :last_name
  validates :first_name
  end
  with_options presence: true, format: { with: /\A[ァ-ン]+\z/} do
  validates :last_name_kana
  validates :first_name_kana
  end
  validates :birthday,         presence: true

  has_many :group_users
  has_many :groups, through: :group_users
    # accepts_nested_attributes_for :group_users

  has_many :messages
end
#GroupUserModel

class GroupUser < ApplicationRecord
  belongs_to :group
  belongs_to :user
end
#GroupUsers

class CreateGroupUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :group_users do |t|
      t.references :group,  foreign_key: true
      t.references :user,   foreign_key: true
      t.timestamps
    end
  end
end
#Group

class CreateGroups < ActiveRecord::Migration[6.0]
  def change
    create_table :groups do |t|
      t.string    :name,          null: false
      t.text      :text,          null: false
      t.integer   :category_id,   null: false
      t.integer   :genre_id,      null: false
      t.timestamps
    end
  end
end
#userの関係のある部分

create_table :users do |t|
      ## Database authenticatable
      t.string  :nickname,             null: false
      t.string  :email,                null: false, default: ""
      t.string  :encrypted_password,   null: false, default: ""
      t.string  :last_name,            null: false
      t.string  :first_name,           null: false
      t.string  :last_name_kana,       null: false
      t.string  :first_name_kana,      null: false
      t.date    :birthday,             null: false
      t.integer :category
      t.integer :genre

長文になってしまいましたが、お読み頂きありがとうございます。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

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

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る