web系エンジニアを目指す私、siが学習のアウトプットをメインにプログラミングについての記事を書いていきます。

【Rails】投稿機能(index,show,new,create)ページネーションの実装

2021/12/14
 
この記事を書いている人 - WRITER -

 

こんにちは!

web系エンジニアを目指して学習中のsiと申します^ ^

 

この記事の対象者

  • 投稿機能(index,show,new,create)を実装したい方
  • ページネーション機能を実装したい方

 

今回の記事では、投稿機能・ページネーションの実装方法について解説していきます!

 

今回実装するアクション

アクション名 使用方法
index リソースの一覧表示
show リソースの詳細表示
new リソースの新規作成
edit リソースの編集
create リソースを新規作成して保存する
update リソースの更新
destroy リソースの削除

 

基本的な7つのアクションについて気になる人は、以下の記事を参考にしてみてください!

【Rails】HTTPリクエストと7つのアクションの関係性について解説!

 

※この記事で出てくる「%」はプロンプトなので実際に入力する必要はありません

 

マシンスペック

 

参考までに私のマシンスペックをご紹介しておきます。

  • macOS Big Sur 11.5.1
  • Macbook Pro(13-inch,2020,Four Thunderbolt 3 ports)
  • intel Core i5
  • メモリ 16GB
  • ストレージ 512GB
  • 使用シェル zsh

 

 

投稿機能の実装

 

事前に、deviseによるUserモデルに作成を行っている前提になるので、

まだ、作成していない方はこちらの記事を参考に作成してみてください。

【超簡単】deviseを使用して名前とパスワードでのログイン機能を実装する!

 

当記事では投稿モデル・コントローラの名称を「Output」としてますが、他の名称でも問題ありません。

⇨「Post」、「Tweet」など

 

1 Outputモデルの作成・アソシエーションの設定

% rails g model Output title:string body:text user_id:integer
% rails db:migrate

stringとtextの違いは、使用可能な文字数の違いです。

stringは最大255文字のため「タイトル」など、文字数をあまり使わない要素に対して使用します。

user_idはUserモデルとの関連付けを行うために作成します。

 

・Userモデルにアソシエーションの記述をする

# app/models/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 :outputs  #追加
end

 

・Outputモデルにアソシエーションの記述をする

class Output < ApplicationRecord

  belongs_to :user  #追加
end

 

このように、2つのモデルにアソシエーションを設定することで、

Outputモデルのuser_idカラムが、Userモデルのidカラム(Primary Key)に対するForeign Keyとなります。

つまり、投稿を行ったUserのidカラムが、Output(投稿)のuser_idカラムに格納されるということです。

 

こうすることで、

どのUserが、どのOutput(投稿)を行ったのか、関連付けを行う事ができます。

 

参考記事

 

2 ルーティングの編集

# config/routes.rb

root "outputs#index"
resources :outputs

ここではルートURLを投稿モデルのindexページに設定しています。

また、resouorcesで投稿モデルの基本的な7つのアクションURLを設定しています。

 

3 indexページの作成・編集

・indexページの作成

% touch app/views/outputs/index.html.erb

 

・indexページの編集

# app/views/outputs/index.html.erb

<% if user_signed_in? %>
  <%= button_to "投稿", {controller: 'outputs', action: 'new'}, {method: :get} %>
<% end %>


<% @outputs.each do |output| %>
  <span>投稿者:</span><%= output.user.name %>
  <%= output.body %>
<% end %>

if user_signed_in?はユーザーがログインしているかを判定してくれる、

deviseを導入することで使用出来るようになるヘルパーメソッド。

 

上の記述だと、ログインしている時のみ投稿ボタンを表示させている。

ちなみに、button_toはボタンを簡単に作成することが出来るヘルパーメソッドです。

 

参考記事

 

ここまでで以下のような画面になっているはずです

 

 

4 newページの作成・編集

・formパーシャルの作成

% touch app/views/outputs/_form.html.erb

 

・formパーシャルの編集

# app/views/outputs/_form.html.erb

<%= form_with model: @output do |f|%>

  <div class="field">
    <%= f.label :title, "タイトル" %></br>
    <%= f.text_field :title%>
  </div>

  <div class="field">
    <%= f.label :body, "本文" %></br>
    <%= f.text_area :body%>
  </div>

  <div class="submit">
    <%= f.submit "送信"%>
  </div>

<% end %>

 

・newページの作成

% touch app/views/outputs/new.html.erb

 

・newページの編集

# app/views/outputs/new.html.erb

<%= render 'form' %>

先ほど作成したformパーシャルを表示させるための記述を追加します。

 

5 outputsコントローラの作成・編集

・outputsコントローラの作成

% rails g controller outputs

 

・outputsコントローラーの編集

# app/controller/outputs_controller.rb

def index
  @outputs = Output.order(created_at: :desc)
# 投稿順(最新順)にデータを表示させるようにする
end

def new
  @output = Output.new
# 空のOutputインスタンスを生成する
end

def create
  @output = Output.new(output_params)
# newページで入力した内容が格納された状態のインスタンスが飛んでくる
  @output.user_id = current_user.id
# user_idカラムにcurrent_userのidを代入する
  if @output.save
    redirect_to root_path
  else
    render 'new'
  end
end

private
  def output_params
    params.require(:output).permit(:title, :body)
  end

上記の記述の流れを簡単に説明すると、こんな感じです

1. indexページにある投稿ボタンをクリックするとnewページに飛ぶ

2. newページで投稿内容を入力後、送信ボタンをクリックするとcreateアクションへ飛ぶ

3. createアクションでは、privateメソッド内にあるストロングパラメータを通ってデータが保存される

4-1. 保存に成功すると、redirect_toでindexページへ飛び、投稿した内容が確認できる

4-2. 保存に失敗すると、renderで2の処理へ戻る

 

renderとredirect_toの違いについては、こちらの記事を参考にしてみてください!

【Rails】renderとredirect_toの違いは ?使い分け方について解説!

 

ストロングパラメータ(output_params)を経由する事で、

不正な情報を保存することを避ける。

 

また、ストロングパラメータをprivateの中に記述することで、誤って外部から呼び出されないように出来る。

 

これで、indexページの投稿ボタンを押すと以下の画面が表示されるようになります。

投稿内容を入力後、送信ボタンをクリックします

すると、このようにindexページへ飛び、投稿したデータが反映されていることが分かります

 

 

6 ページネーションの実装

・ページネーションを実装するためのGemである「kaminari」をGemfileに記述する

# Gemfile

gem 'kaminari'

 

・「kaminari」のインストール

% bundle

 

・ページネーションが表示されるようにindexアクションの編集を行う

# app/controllers/outputs_controller.rb

def index
  @outputs = Output.order(created_at: :desc).page(params[:page]).per(10)
end

これで、10投稿以上存在する場合は次ページに表示されるようになる。

 

・indexページの編集も行う

# app/views/index.html.erb

<% if user_signed_in? %>
  <%= button_to "投稿", {controller: 'outputs', action: 'new'}, {method: :get} %>
<% end %>

<% @outputs.each do |output| %>
  <span>投稿者:</span><%= output.name %>
  <%= output.title %><br>
<% end %>
<%= paginate @outputs %>  # 追加

 

実際に10投稿以上した場合、以下のような画面になる

・1ページ目

・2ページ目

 

以上で、ページネーションを機能を実装した投稿機能の完成です!

 

最後にshowアクションを追加しましょう!

あと少しで完成です!頑張りましょう♪

 

 

7 showページの作成・編集

・showアクションの追加

# app/controllers/outputs_controller.rb

def show
  @output = Output.find(params[:id])
end

 

・showページの作成

% touch app/views/outputs/show.html.erb

 

・showページの編集

# app/views/outputs/show.html.erb

<h3>タイトル</h3>
<%= @output.title %><br>

<h3>本文</h3>
<%= @output.body %>

titleカラム・bodyカラムの中身を表示するようにする。

 

・indexページの編集

# app/views/outputs/index.html.erb

<% if user_signed_in? %>
  <%= button_to "投稿", {controller: 'outputs', action: 'new'}, {method: :get} %>
<% end %>


<% @outputs.each do |output| %>
  <span>投稿者:</span><%= output.user.name %><br>
  <span>タイトル:<%= link_to output.title, "outputs/#{output.id}" %><br>  #追加
<% end %>
<%= paginate @outputs %>

各投稿に、showページへ飛ぶためのリンクを設定します。

 

これでindexページの投稿タイトルがリンク表示になります

リンクをクリックしてみると、このように投稿詳細ページに飛びます

 

これで投稿機能(index,show,new,create)の実装は完了です!

お疲れ様でした^ ^

 

最後に

 

今回は投稿を行うための機能実装方法、ページネーションの実装方法について解説してみました!

 

次回は、投稿編集・投稿削除の機能実装方法について解説したいと思います!

 

今後も、どんどん記事投稿を行なっていくので、

よければ、応援の方お願い致します(*^ω^*)

 

それでは!

 

この記事を書いている人 - WRITER -

- Comments -

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


Copyright© .i DO WHAT I WANT , 2021 All Rights Reserved.