Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

はじめに

現在、開発中の「小説執筆ツールアプリ」で各ページの共通部品となるサイドバーを設置するに当たって、あまりに非オブジェクト指向な私の書き方を見かねた先輩エンジニアのKさんより、脱ファットコントローラ的な書き方を伝授していただき、それがオブジェクト指向の理解を深める上で非常にヒントとなる内容でしたので、投稿させて頂きます!

サイドバーの中に貼りたいやつ

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

これを実現するにはコントローラから、
“現在ログイン中のユーザーの登録した小説のタイトル”と“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>

以上です!

かなり初歩的な内容で恐縮ですが、なにか誤りがあればご指摘をいただけるとありがたいです!

Yosuke_Narumi
駆け出しエンジニアです! 現在はRailsで自社サービスのアプリの開発をしています! 先月末(2020/11)、入社1月で「小説執筆アプリ-Mono-」をリリースさせていただきました! https://www.mono-kaki.site/
evolu
「みんながわくわくする世界をつくる」ために日々技術の研鑽をしていきます
https://evolu.tokyo
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away