Rails 掲示板作成機能 解説

Rails 掲示板作成機能 手順　（自分用）

#Userモデルに、Boardモデルとの関連付けを追加

Userと関連付けて、掲示板を作成するため、UserとBoardのhas_many関連をモデルに定義。

```rb:app/models/user.rb
class User < ApplicationRecord
   authenticates_with_sorcery!
 
   has_many :boards, dependent: :destroy
 
   validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
   validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
```
###has_many :boards, 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」を使って、ユーザーが削除されたらそのユーザーが投稿した掲示板も削除されるようにする。

#掲示板作成のrouteを追加

```rb: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
```
・掲示板作成のため、:boardsに、newとcreateを追加

#掲示板作成のコントローラーを実装

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

  def new
    @board = Board.new
  end

  def create
    @board = current_user.boards.build(board_params)#下記で説明
    if @board.save
      redirect_to boards_path, success: t('defaults.message.created', item: Board.model_name.human)
    else
      flash.now['danger'] = t('defaults.message.not_created', item: Board.model_name.human)
      render :new
    end
  end

  def show
    @board = Board.find(params[:id])
  end

  private

  def board_params
    params.require(:board).permit(:title, :body)
  end
end
```
・@board = current_user.boards.build(board_params)は「ログインしているユーザーのBoardデータの登録」することによって自分以外に掲示板の編集や削除をできなくするもので、「current_user.boards」でcurrent_userのidをBoardモデルのカラムであるuser_idに代入し、「build」で初期化（投稿作成）する。これで、投稿が誰のものなのかuser_idによって判断できるようになる。
＊「current_user」はsorceryのメソッドでログイン中のユーザーの値が入っている。
＊「boards」は、モデルで設定されているhas_many :boardsによって使えるようになったメソッド。userオブジェクトで使える。
＊アソシエーションでオブジェクトを初期化するときはbuildを使う。挙動はnewと同じだが、関連付けされていることが視覚的にわかるようにしている。
*「current_user.boards.build(params)」でログインしているユーザーのidを投稿の「user_id」に代入して、コントローラーのpostメソッドでBoard.newからデータが送られてきている「(board_params)」を引数に「build(新規作成)」が行われている。

#掲示板作成のビューを実装


```rb:app/views/boards/new.html.erb
<div class="container">
   <div class="row">
     <div class="col-lg-8 offset-lg-2">
       <h1><%= t('.title') %></h1>
       <%= render 'form', { board: @board } %>
     </div>
   </div>
 </div>
```
・<%= render 'form', { board: @board } %>は、部分テンプレート（_form.html.erb）を呼びだす際に変数「board」をインスタンス変数「@board」として扱うという定義

```rb:app/views/boards/_form.html.erb
<%= form_with model: board, local: true do |f| %>
   <div class="form-group">
     <%= f.label :title %>
     <%= f.text_field :title, class: 'form-control' %>
   </div>
   <div class="form-group">
     <%= f.label :body %>
     <%= f.text_area :body, class: 'form-control', rows: 10 %>
   </div>
 
   <%= f.submit class: 'btn btn-primary' %>
 <% end %>
```
＊「form_with　model」の形を使う場合は、データベースにデータを保存する時に使う。
＊modelオプションを使う場合、form_withの引数にはモデルクラスのインスタンスを指定する。
＊「model: board」でBoardモデルを基にフォームが作られる
＊モデルクラスのインスタンスとは保存したいテーブルのクラスのインスタンスのことで、１つのレコードを表すオブジェクトになり、テーブルのカラムに相当する属性を持つ。
＊パーシャルの場合はコントローラーとの関連をなくすためにインスタンス変数を使用しないので変数を使う。（再利用性が低くなるから）

```rb:app/controllers/boards_controller.rb(モデルクラスのインスタンスを指定)
  def new
    @board = Board.new #new（作成）したBoardモデルクラステーブルのインスタンスを@boardに代入して取得。
  end
```