3
4

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.

Rails 掲示板一覧機能 解説

Last updated at Posted at 2021-11-03

Rails 掲示板一覧機能 手順 (自分用)

#Bordモデルを作成する

ターミナル
$ bundle exec rails generate model board title:string body:text user:references

・モデルとマイグレーションファイルが作られる。
・掲示板を作るにあたってBordモデルを作る。その際に「user:references」をつけることで、Userモデルを参照してくれるようになる。(Bordモデルには「belongs_to :user」が追加され、マイグレーションファイルには、「t.references :user, foreign_key: true」が追加される。*後で説明)

#BoardモデルとUserモデルの関連付けと、バリデーションの設定

app/models/user.rb
  has_many :bords, dependent: :destroy

・has_manyはテーブル同士を関連づけるもの。そのクラス(ここではUser)のidを外部キーとして抱える他のクラス(ここではBord)があり、UserはBordを複数登録可能であるということ。*has_many(User)はbelongs_to(Bord)を何個も投稿できるよ!みたいなイメージ。
・「dependent: :destroy」オプションをつけることによって「boardに紐づいたuserが消されたら該当boardも削除」という作業を行なってくれる。親にあたるuserが削除された際に、子にあたるbordだけが残ると「board(子)があるのにuser(親)がいない」ということになり、整合性が取れずバグの原因になる為、「dependent: :destroy」を使う。

app/models/board.rb
class Board < ApplicationRecord
  belongs_to :user

  validates :title, presence: true, length: { maximum: 255 }#「presence: true」で入力必須。「length: { maximum:  }」は文字数制限のバリデーション。今回は、255字以内という制限。
  validates :body, presence: true, length: { maximum: 65_535 }#文字数制限が65文字以上535文字以下。
end

・belongs_toはそのクラス(ここではBord)が、ある別のクラス(ここではUser)に従属しており、従属先のクラスのid(ここではuser_id)を外部キーとして抱えているということ。

#マイグレーションファイル

db/migrate/XXXXXXXXXXXXXX_create_boards.rb
class CreateBoards < ActiveRecord::Migration[5.2]
  def change
    create_table :boards do |t|
      t.string :title, null: false
      t.text :body, null: false
      t.references :user, foreign_key: true

      t.timestamps
    end
  end
end

・titleとbodyにnull: falseを追加
・t.references :user, foreign_key: trueは、bordテーブルに「user_id」という外部キーカラムを追加するもの。*掲示板に投稿した際に、user_idカラムがあることで、削除や、編集を自分以外が出来ないようにする為。

ターミナル
$ rails db:migrate

・マイグレートする。

#掲示板一覧のコントローラーを実装

・bordに対応するコントローラーを作成

ターミナル
$ bundle exec rails generate controller boards

・コントローラ、view、decoratorが作成される。
#####生成されたBoardsControllerに、掲示板の一覧をDBから取得する処理を追加。

app/controllers/boards_controller.rb
class BoardController < ApplicationController
  def index
    @boards = Board.all.includes(:user).order(created_at: :desc)#includesメソッド
  end
end

#####includesメソッド

app/controllers/boards_controller.rb
class BoardController < ApplicationController
  def index
    @boards = Board.all.order(created_at: :desc)
  end
end

・includesメソッドを使わない場合、bord(投稿)の数だけuserテーブルにアクセスすることになり、データ取得に時間がかかる。その結果、アプリケーションのパフォーマンスが下がる。これを「N+1問題」という
・これを解決するためにincludesメソッドを使用する。

includesメソッド
モデル名.includes(:アソシエーションで紐付くモデル名)

・includesメソッドは、引数に指定された関連モデルを1度のアクセスでまとめて取得するメソッド
・bordテーブルに対して1回、Userテーブルに対しても1回のアクセスで全ての情報を取得できるようになる。

#掲示板作成のrouteを追加

config/routes.rb
Rails.application.routes.draw do
  root 'static_pages#top'

  get 'login', to: 'user_sessions#new'
  post 'login', to: 'user_sessions#create'
  delete 'logout', to: 'user_sessions#destroy'

  resources :users, only: %i[new create]
  resources :boards, only: %i[index new create]#この部分を追加
end

#掲示板一覧のViewを実装する

app/views/boards/index.html.erb
<div class="container pt-3">
   <div class="row">
     <div class="col-lg-10 offset-lg-1">
       <!-- 検索フォーム -->
       <form>
         <div class="input-group mb-3">
           <input class="form-control" placeholder="検索ワード" type="search" />
           <div class="input-group-append">
             <input type="submit" value="検索" class="btn btn-primary" />
           </div>
         </div>
       </form>
     </div>
   </div>
 
   <!-- 掲示板一覧 -->
   <div class="row">
     <div class="col-12">
       <div class="row">
         <% if @boards.present? %>
           <%= render @boards %> #下記で説明
         <% else %>
           <p><%= t('.no_result') %></p>
         <% end %>
       </div>
     </div>
   </div>
 </div>

・ 「<%= render partial: 'board', locals: { board: @board }%>」の省略形は「<%= render 'board', { board: @board } %>」となっており、さらにインスタンス変数名(@board)とファイル名(_board.html.erb)が同じ場合「<%= render @boards %>」のような省略形にすることができる。

app/views/boards/_board.html.erb
<div class="col-sm-12 col-lg-4 mb-3">
  <div id="board-id-<%= board.id %>">
    <div class="card">
      <%= image_tag 'app/assets/images/に配置した写真のデータ名', class: 'card-img-top', size: '300x200' %>
      <div class="card-body">
        <h4 class="card-title">
          <a href="#">
            <%= board.title %>
          </a>
        </h4>
        <div class='mr10 float-right'>
          <a href="#"><%= icon 'fas', 'trash', class: 'pr-1' %></a>
          <a href="#"><%= icon 'fa', 'pen' %></a>
        </div>
        <ul class="list-inline">
          <li class="list-inline-item">
            <%= icon 'far', 'user' %>
            <%= board.user.decorate.full_name %>
          </li>
          <li class="list-inline-item">
            <%= icon 'far', 'calendar' %>
            <%= l board.created_at, format: :long %>
          </li>
        </ul>
        <p class="card-text"><%= board.body %></p>
      </div>
    </div>
  </div>
</div>

#ヘッダーに掲示板一覧ページへのリンクを追加

_header.html.erb
<div class="dropdown-menu dropdown-menu-right">
  <%= link_to t('boards.index.title'), boards_path, class: 'dropdown-item' %>
  <%= link_to '掲示板作成', 'new_board_path', class: 'dropdown-item' %>
</div>

・掲示板一覧のリンクをboards_pathに変更

3
4
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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?