ログイン中のユーザーで掲示板の新規作成をする

UserモデルとBoardモデルにアソシエーションを設定

Userと関連付いたboardを作成するので、has_manyをUserモデルに定義する。

class User < ApplicationRecord
  authenticates_with_sorcery!
  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
end

controller

UserモデルとBoardモデルにアソシエーションが定義されている場合の記述。
以下のように記述した場合、登録に成功しない。

class BoardsController < ApplicationController
  skip_before_action :require_login, only: %i[index create]
  def create
    @board = Board.new(board_params) ←ここ
    if @board.save
      redirect_back_or_to boards_path, info: '掲示板を作成しました'
    else
      flash.now[:danger] = '掲示板を作成できませんでした'
      render 'new'
    end
  end

  private

  def board_params
    params.require(:board).permit(:title, :body)
  end
end

原因

user_idカラム作成時にNOT NULL制約をつけているので、上記コードだとuser_idがnilになってしまう。

ログインユーザーに関連した掲示板のオブジェクトを作成するには

@board = current_user.boards.build(board_params)

current_user.boards.newとすることで、user_idを登録したboardオブジェクトを初期化できる。引数としてパラメータ(board_params)を渡すことでフォームに入力されたオブジェクトを作成することができる。アソシエーションで定義されたオブジェクトを初期化する際はnewではなくbuildを使う。(どちらを記述しても挙動は変わらない)
また、以下のようにmergeを使ってuser_idを用意することもできるが、

Board.new(board_params.merge(user_id: current_user.id))

アソシエーション関連であるオブジェクトは強調したほうが良いので、モデルのアソシエーションに関連性のない情報を登録する時にmergeは使うと良い。

view

ビューはパーシャルを使い表示させる。

      <%= form_with model:board, local: true do |f| %>
        <%= render 'shared/error_messages', object: f.object %> 
        <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", low: "10", style: "height: 200px" %>
        </div>
        <%= f.submit "登録する", class: "btn btn-primary" %>
      <% end %>
    </div>
  </div>
</div>

パーシャルをnew.htmlで読み込む。

<div class="container">
  <div class="row">
    <div class="col-lg-8 offset-lg-2">
      <h1>掲示板作成</h1>
      <%= render 'form', { board: @board } %>
    </div>
  </div>
</div>