【Rails】全ページに設置するサイドメニュー用のコントローラを作りオブジェクト指向っぽく書いてみる


はじめに

プログラミング初心者です!オブジェクト指向について学習中です!
自作webサービスの「サイドバー」の部分のコントローラ view間の実装においてオブジェクト指向の「名前付けのい概念」を意識してコードを書き直してみました!

サイドバーの中に貼りたい要素

  • ユーザーが執筆登録した小説のタイトル
  • その小説の執筆するページへのリンク

これを実現するにはコントローラから、
“現在ログイン中のユーザーの登録した小説のタイトル”と“id”のカラム値
をインスタンス変数で取得する必要がある。

サイドバーを設置するページ

1.執筆一覧ページ 
writings_controller.rb

2.タイトル/あらすじページ
novels_controller.rb)

3.プロットページ
plots_controller.rb

4.登場人物ページ
characters_controller.rb)

5.パスワード変更ページ
passwordresets_controller.rb

流れ

①これらのページに対応した各コントローラでidとtitleカラムをインスタンス変数で取得

②コントローラで取得したインスタンス変数を使い、サイドバーのビューに
 "ユーザーが執筆登録した小説のタイトル”と"その小説の執筆するページへのリンク”
 に描画

③そのビューをパーシャル化して全ページビューに貼ります

良い例・悪い例

今回のアプリのテーブルにはユーザーに該当するauthorsテーブル(current_user)とそのユーザーが登録する小説に該当するnovelsテーブルがあります。
この場合、目的である「ユーザーが登録した小説のタイトル」と「その小説の執筆するページへのリンク」をサイドバーに設置するにはcurrent_user.novelsのnovels(子テーブルの)id、titleカラムが必要になります。
つまり上記5つのコントローラでこのテーブル情報の取得をし、サイドバーのビューにインスタンス変数で渡してあげる必要となりますが、この書き方において、オブジェクト指向に則った良い書き方と悪い書き方を比べてみたいと思います!

悪い例

controller
def index


 @novels_id = current_user.novels.order(created_at: :desc).pluck(:id)
 @novels_title = current_user.novels.order(created_at: :desc).pluck(:title)
end
view
<% @novels_id.zip(@novels_title) do |novels_id, novels_title| %>
 <%= link_to "/novels/#{novels_id}/writings/new" do %>
 <%= novels_title %>
 <% end %>
<% end %>

ユーザーが登録している小説のタイトルとその小説の執筆作成リンク生成のためのidを取得するため明示的に情報取得し、このままビューで扱ういうオブジェクト指向を無視した書き方になります!
この場合、上記5つのコントローラの全アクションで同じ記述が必要になってしまいます>_<
 

「ログイン中のユーザーが登録した小説」というオブジェクトを扱ったCurrentUsersNovelsコントローラを生成

controller
class CurrentUsersNovelsController < ApplicationController
before_action :set_all_self_novels

 def set_all_self_novels
  @novels = current_user.novels.order(created_at: :desc)
 end
end

この様にbefore_actionでデフォルト取得させてあげれば、このクラスを継承した下位の全クラス
でこのインスタンス変数が使えます!

なので、この記述をして、、

controller
class HogeController < CurrentUsersNovelsController 

end

このように該当する5つのコントローラにCurrentUsersNovelsControllerを継承させれば
@novels = current_user.novels.order(created_at: :desc)
がそのコントローラで扱える様になり、下記の様に記述も非常に簡潔にまとまります!

良い例

controller
def index
#その他コード略
end
view
<% @novels.each do |novel|  %>
 <%=  link_to "/novels/#{novel.id}/writings/new" do %>
 <%= novel.title %><br>
 <% end %>
<% end %>
</li>

以上です!