Ryota400’s blog

エンジニアを目指して書いてます。

掲示板の一覧機能の作成

掲示板の一覧機能の作成の確認ポイント

・Boardモデルのバリデーション

 validates :title, presence: true, length: { maximum: 数 }
 validates :body, presence: true, length: { maximum: 数 }

・Userモデル

has_many :boards, dependent: :destroy 

dependent: :destroyを追加することで、 「親モデルを削除する際に、その親モデルに紐づく「子モデル」も一緒に削除できる」ようになります。 例えばユーザーが退会した場合、そのユーザーが投稿した記事も全て消えるように設定するのであれば、必須な知識。

・N+1問題 データベースからデータを取り出す際に、たくさんのSQLを発行して、アプリケーションの動作が重くなってしまう問題だ。 原因は、複数のテーブルに関連(アソシエーション)があるからです。あるテーブルの一覧を取得するために、SELECTを一度実行すると、そのテーブルに関連したテーブルのデータを取得するために、またSELECTが実行されてしいる。

includesメソッドで関連付けを一括読み込みをする includesは、関連助けられたテーブルのデータを参照するメソッドだ。このメソッドを使うと、あるモデルからデータを取得する際に、関連付けされたモデルのデータもいっしょに取得してくれる。

class BoardsController < ApplicationController

 def index
   @boards = Board.all.includes(:user).order(created_at: :desc) 
 end
end

掲示板のパーシャルをrenderしていること collectionをeachするより、部分テンプレートをrenderで回すほうがパフォーマンスがよく、以下の様にコード量が減り、可読性が上がる。 app/view/boards/index.html.erb

<%= render @boards %>

・Boardモデルのuser_idに外部キー制約がついていること

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
      # このようにreferences型になっていればOK

      t.timestamps
    end
  end
end

外部キー制約をつけることで、存在しないユーザーのIDが登録されて、不整合なデータが発生することをDB側から拒否できる。

・アクセス制御をさせたいコントローラー(BoardsControllerやUsersController)で個別にbefore_actionを記載するのではなくて、継承元の親クラスであるApplicationControllerに記載することで処理を共通化させる

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def not_authenticated
    redirect_to login_path, warning: t('defaults.message.not_authenticated')
  end
end

これで他のControllerを追加で実装する際にも、アクセス制御の処理を忘れずに適用させることができる。 ログイン画面ではアクセス制御を適用させたくないのでUserSessionsContollerにはskip_before_actionで継承元のbefore_actionで定義した処理を無効化させることができる。 not_authenticatedメソッド ログインできなかった(認証されなかった)場合に、このメソッドに記述した処理が行われる。

参考文献

[Rails] dependent: :destroy について - Qiita

N+1問題をincludesメソッドで解決する【Day 8/30 2nd】|K.Tawara|note