20
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Ruby on rails]グループ作成①

Last updated at Posted at 2021-07-10

初めに

プログラミング学習初めて1ヶ月と少しです。 理解不足、誤りがありましたらご指摘いただけますと幸いです。

グループ作成機能①

本の投稿サイトを作成しています。①の今回は、グループを作れるようにします。 この記事ではあるユーザーがグループを作る流れをまとめています。 グループに参加する機能は無いです。それは②でやります。

今回の記事でできるようになること

*グループを作成するリンクの表示。 *グループを作れる。(②の記事でメンバー増やせるようにします) *作成した人はグループオーナー *グループ一覧画面作成。 *グループのオーナーであればグループの編集ができる *グループの詳細画面(①の段階では質素な画面です。)

グループの編集は、グループの作成者のみが行えます。(削除機能は無しです。)
画面は以下の4つ。
グループ一覧画面。
グループ詳細画面。
グループ編集画面。
グループ作成画面。

「作成イメージ」

スクリーンショット 2021-07-08 17.46.08.png

まずアソシエーション考える

ユーザー:Group= 1:N(複数) Group:ユーザー=1:N(複数) なので、中間テーブルが必要になります。 中間テーブルは、GroupUserとして、外部キーとしてuser_idとgroup_idを持たせます。

Groupテーブルのカラムは
id
name
introduction
image_id (グループ画像も設定可能にします!)
owner_id (グループ作成者をowner_idにします)

作成開始

$ rails g model group
$ rails g model group_user```
中間テーブルであるgroup_userは何かするわけではなく、groupとユーザーの外部キーを持ってくれてるだけなので、コントローラーはいりません。

<h2>マイグレーションファイルの内容</h2>

```perl:20~~??_create_groups.rb
class CreateGroups < ActiveRecord::Migration[5.2]
  def change
    create_table :groups do |t|
      t.string :name
      t.text :introduction
      t.string :image_id
      t.integer :owner_id

      t.timestamps
    end
  end
end
20~~??_create_group_users.rb
class CreateGroupUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :group_users do |t|
      t.references  :user,  index: true, foreign_key: true
      t.references  :group, index: true, foreign_key: true
      
      t.timestamps
    end
  end
end

ここの記述は簡単にいうと、group_usersに外部キーとしてuser_idとgroup_idを登録しています。以下の記事がわかりやすかったです。reference使えば、自動でindexもひっぱってくるということなので、index:trueはなくても良いようです。

忘れずにマイグレーション!

rails db:migrate

モデルファイルにアソシエーション記述

グループの削除機能はないので、dependent: :destroyの記述はないです。

group_user.rb
class GroupUser < ApplicationRecord
  belongs_to :user
  belongs_to :group
end
group.rb
class Group < ApplicationRecord
  has_many :group_users
  has_many :users, through: :group_users

  validates :name, presence: true
  validates :introduction, presence: true
  attachment :image, destroy: false
end

現状、destroy:falseがわかりませんdestroyはできない という意味なのでしょうか。

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

  has_many :books
  has_many :group_users   #ここ!
  has_many :groups, through: :group_users
  has_many :favorites, dependent: :destroy
  has_many :book_comments, dependent: :destroy
  attachment :profile_image, destroy: false

  validates :name, length: { minimum: 2, maximum: 20 }, uniqueness: true
  validates :introduction, length: { maximum: 50 }
end

has_many :groups, through: :group_users
これは、userは、group_usersという中間テーブルを通じてgroupsにアクセスできるという記述。
Userのボス「そりゃーグループの情報掴めるよ〜group_usersを通じて聞けばいいんだよ」みたいな。group_usersさんは仲介役ですね。
なんだか、ちんぷんかんだった中間テーブルがわかってきたような気がします。
Userのボスからしてみても、中間テーブルという仲介役がいた方がラクなんですよね。

ルーティングの設定

resources :groups, except: [:destroy]

もちろん

[:index, :show, :edit, :create, :update, :new, :show]
```のような記述でもいけると思います。


<h2>コントローラー作成</h2>


```perl:groups_controller.rb
class GroupsController < ApplicationController
  before_action :authenticate_user!
  before_action :ensure_correct_user, only: [:edit, :update]

  def index
    @book = Book.new
    @groups = Group.all
  end

  def show
    @book = Book.new
    @group = Group.find(params[:id])
  end

  def new
    @group = Group.new
  end

  def create
    @group = Group.new(group_params)
    @group.owner_id = current_user.id
    if @group.save
      redirect_to groups_path
    else
      render 'new'
    end
  end

  def edit
  end

  def update
    if @group.update(group_params)
      redirect_to groups_path
    else
      render "edit"
    end
  end

  private

  def group_params
    params.require(:group).permit(:name, :introduction, :image)
  end

  def ensure_correct_user
    @group = Group.find(params[:id])
    unless @group.owner_id == current_user.id
      redirect_to groups_path
    end
  end
end

本の投稿サイトなので、@book等の記述も入ってしまっています。

Viewページ

スクリーンショット 2021-07-08 17.43.22.png

↑の部分の記述。
スクリーンショット 2021-07-08 17.45.37.png

<div><%=link_to "グループを作成する",new_group_path %> | <%=link_to "グループ一覧",groups_path %></div>
その他のview

部分テンプレートで飛ばしています。

edit.html.erb
<div class='container'>
  <div class='row'>
    <div class="col-sm-12 col-md-8 col-lg-5 px-5 px-sm-0 mx-auto">
      <h3>Editing Group</h3>
        <%= render 'form', group: @group %>
  </div>
</div>
_form.html.erb
<%= form_with model: group, local: true do |f| %>
  <div class="form-group">
    <%= f.label :グループ名 %>
    <%= f.text_field :name, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= f.label :紹介文 %>
    <%= f.text_area :introduction, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= f.label :グループ画像 %>
    <%= f.attachment_field :image, class: "form-control-file" %>
  </div>

  <div class="form-group">
    <%= f.submit class: 'btn btn-info' %>
  </div>
<% end %>
index.html.erb
#関連部分のみ
<div class='col-md-8 offset-md-1'>
      <h2>Groups</h2>
      <table class='table table-hover table-inverse'>
        <thead>
          <tr>
            <th></th>
            <th>グループ名</th>
            <th>紹介文</th>
            <th colspan="3"></th>
          </tr>
        </thead>
        <tbody>
          <% @groups.each do |group| %>
            <tr>
              <td><%= attachment_image_tag(group, :image, :fill, 50, 50, fallback: "no-image-icon.jpg") %></td>
              <td><%= link_to group.name, group_path(group) %></td>
              <td><%= group.introduction %></td>
              <td>
                <% if group.owner_id == current_user.id %>
                  <%= link_to 'Edit', edit_group_path(group), class: "btn btn-sm btn-success" %>
                <% end %>
              </td>
            </tr>
          <% end %>
        </tbody>
      </table>
    </div>
new.html.erb
<div class='container'>
  <div class='row'>
    <div class="col-sm-12 col-md-8 col-lg-5 px-5 px-sm-0 mx-auto">
      <h3>Create Group</h3>
        <%= render 'form', group: @group %>
    </div>
  </div>
</div>
show.html.erb
<div class='container px-5 px-sm-0'>
  <div class='row'>
    <div class='col-md-3'>
      <h2>User info</h2>
      <%= render 'users/info', user: current_user %>
      <h2 class="mt-3">New book</h2>
      <%= render 'books/form', book: @book %>
    </div>
    <div class='col-md-8 offset-md-1'>
      <h2>Group Detail</h2>
      <table class='table table-hover table-inverse'>
        <tr>
          <td><%= attachment_image_tag(@group, :image, :fill, 50, 50, fallback: "no-image-icon.jpg") %></td>
          <td><%= @group.name %></td>
          <td><%= @group.introduction %></td>
          <td>
            <% if @group.owner_id == current_user.id %>
              <%= link_to 'Edit', edit_group_path(@group), class: "btn btn-sm btn-success" %>
            <% end %>
          </td>
        </tr>
      </table>
    </div>
  </div>
</div>

終わり

これを見ながら、再度実装したところ、なんとかできましたので、 問題ないかと思います!
20
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?