【Rails】投稿機能(index,show,new,create)ページネーションの実装
こんにちは!
web系エンジニアを目指して学習中のsiと申します^ ^
この記事の対象者
- 投稿機能(index,show,new,create)を実装したい方
- ページネーション機能を実装したい方
今回の記事では、投稿機能・ページネーションの実装方法について解説していきます!
今回実装するアクション
アクション名 | 使用方法 |
index | リソースの一覧表示 |
show | リソースの詳細表示 |
new | リソースの新規作成 |
edit | リソースの編集 |
create | リソースを新規作成して保存する |
update | リソースの更新 |
destroy | リソースの削除 |
基本的な7つのアクションについて気になる人は、以下の記事を参考にしてみてください!
※この記事で出てくる「%」はプロンプトなので実際に入力する必要はありません
目次
マシンスペック
参考までに私のマシンスペックをご紹介しておきます。
- macOS Big Sur 11.5.1
- Macbook Pro(13-inch,2020,Four Thunderbolt 3 ports)
- intel Core i5
- メモリ 16GB
- ストレージ 512GB
- 使用シェル zsh
投稿機能の実装
事前に、deviseによるUserモデルに作成を行っている前提になるので、
まだ、作成していない方はこちらの記事を参考に作成してみてください。
当記事では投稿モデル・コントローラの名称を「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の違いについては、こちらの記事を参考にしてみてください!
ストロングパラメータ(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)の実装は完了です!
お疲れ様でした^ ^
最後に
今回は投稿を行うための機能実装方法、ページネーションの実装方法について解説してみました!
次回は、投稿編集・投稿削除の機能実装方法について解説したいと思います!
今後も、どんどん記事投稿を行なっていくので、
よければ、応援の方お願い致します(*^ω^*)
それでは!