30代未経験からWebエンジニアになった私のプログラミング学習日記

【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© 30代未経験からのプログラミング , 2021 All Rights Reserved.