フリーランス
エンジニア
Railsのファットコントローラー 3つの対処法
Bilbase株式会社代表の佐藤です。
前回の記事ではファットモデルに陥るサイクルとその回避方法について書かせていただきましたが、今回は続編として、ファットコントローラーについてふれていきたいと思います。初学者の方にもわかりやすいように書いていきます!
皆さんはプロジェクトでファットコントローラーを経験したことがあるでしょうか?
多言語で経験を積んでいる方は割と回避しやすいものですが、Railsからプログラミングを始める方はハマりやすいポイントかも知れませんね。
まずは結論
・とりあえずビジネスロジックをモデルに移すことを意識する。
・同時進行でリファクタリングするのは諦めて、コントローラーを綺麗にすることに集中する。
初学者の方にありがちな失敗として、目の前にある問題以外のことにも気を取られすぎてしまい、結局どこから手をつければいいかわからなくなるということが挙げられます。慣れていない方は、まず目の前の課題から解決して、コンパクトに学習とリファクタリングを進めていきましょう!
前回のファットモデル解消法でもお話しましたが、エンジニアリングをする中で、最初に抑えておくべき部分を見落としがちな方は一定数いらっしゃると思います。
「もうわかってるから問題ないよ〜」という方はこの記事をスキップしてもらって大丈夫です。
見直しを含めて、もう一度さらっておきたい方々はどうぞご一読ください。
では早速中身を見ていきましょう!
コントローラーの担当は?
めっちゃそもそもの話をしていきます。
Ruby on RailsはMVCアーキテクチャに基づいて3つの要素で構成されています。
「MVC」の「C」が今回登場するコントローラーです。
ここではコントローラーの役割についてサクッと見ていきましょう。
ご覧の通りコントローラーは全体の処理の中で中間地点に位置しています。
つまりコントローラーの役割は「仲介役」ということです。
【もう少し詳細なコントローラーの役割】
- ブラウザからのリクエストを受け取る
- データをモデルに要求する
- データの追加、変更をモデルに指示する
- 適切なViewを選ぶ
- データをViewに渡す
なぜファットコントローラーに陥るのか
ファットコントローラーに陥る原因はただひとつだけ。
実は前項で書かせていただいた「仲介役」という役割を忘れてしまったときに起こるケースです。
一度理解してしまえばファットコントローラーは簡単に攻略できるので、気張らずに頑張りましょう。
まずは下記の図で「Railsがファットモデルに辿り着くまで」をご覧ください。
こちらは前回書かせていただいた、「Railsのファットモデル3つの対処法」でも使用した図です。今回の対象はステージ2のコントローラーですね。
RailsではSkinny Controller, Fat Modelという方針が推奨されていますが、初学者にとっては「なんのこっちゃ」だと思います。
解説
1,まず、ほかのフレームワークをさわったことがない初心者にとって陥りやすい問題がファットビュー。最終的に画面に表示される内容に関するコードが書き込まれるためビューにロジックを書き込んでしまうケースも見られます。
2,問題はここ、Railsに慣れ始めたエンジニアが陥るファットコントローラー。モデルに書くべき処理とコントローラーで必要な処理の使い分けがうまくできずに、コントローラーにロジックが集中するケース。ビューをスリムにすることはできたが、モデルやモジュールをうまく使いこなせていない、コントローラーのコードに無駄が多い場合に陥りやすいです。
3,しっかりModelにロジックを寄せていった結果、待ち構えているのがファットモデルです。Viewとコントローラーをスッキリできた分Modelにロジックが集まるのは当然ですよね。
コントローラーで何をどこまでやればいいのかわからない、ファットコントローラーの状況になってしまいます。
今すぐ使える【3つのファットコントローラー解消方法】
ここでは紹介できる数も限られてきますので、基本的な考え方の手順を3つだけ紹介していければと思います。
ロジックをすべてモデルへ
まずは膨れ上がったコントローラーのロジックをすべてモデルへ移行する気持ちで進めましょう。最初から細かいことを考えるよりも構造が整理されている方が大切です。
❏ポイント
・publicメソッドはアクション(APIモードの場合はAPI)だけにして、それ以外のメソッドはモデルへ移す
・モデルへの移行とリファクタリングは切り分けて考える
❏メリット
モデルに処理を集めることで、結果的にそのモデルの規模感がわかるので、モデル自体の改修が必要か、今後の方針も検討することができるようになる点でいいと思います。
メソッドの行数を減らす
条件に応じてコントローラーで処理を分けたいこともあると思いますが、そのためにメソッドが膨らむと、とんでもなく見通しが悪くなるので注意が必要です。
この内容はモデルでもモジュールでもいえることですので、早めに意識しておくことをおすすめします。
❏ポイント
・before_actionを使う
・繰り返し使う処理はメソッド化してモデルへ
❏メリット
before_actionを使用することによって、コードの行数を減らすことにつなげられます。それだけでなく「DRY」の原則に従ってソフトウェア開発を進めることにもつながると思います。
DRYは「Don’t Repeat Yourself」の略で、ただ「繰り返さない」という受け取り方よりも「開発全体において情報を重複させない」という認識でいてもらったほうがいいかと思います。(この辺りもまた別記事で書いていきます)
コントローラーでbefore_actionを定義することによって、アクションの前に処理を差し込むとができます。一般的には、複数のアクションで共通している処理に関してはbefore_actionで定義するようにしましょう。
before_actionに関しての使用例は以下に記載させていただきました。
class Api::V1: :UsersController < ApplicationController
before_action :set_user, only: %i[show update destroy]
def show
render json: @user.as_json
end
def update
if @user.update(user_params)
render json: { result: 'success' }
else
render json: { result: @user.errors }
end
end
def destroy
if @user.destory(user_params)
render json: { result: 'success' }
else
render json: { result: @user.errors }
end
end
private
def user_params
params.permit(:name_kanji, :name_kana, :email)
end
def set_user
Quser = User.find(params[:id])
end
end
RuboCopでコードを最適化
Railsにはコードを最適化するためのrubocopというgemが存在します。
$ rubocop
こちらコマンドで.rbファイルを解析して、修正するべきコードを表示してくれます。
$ rubocop {ファイル名}
とすることでそのファイルだけの解析もしてくれます。
$ rubocop -a
-aオプションを付けることで自動的にコードを修正してくれるという便利な使い方もあるので覚えておくといいかもしれません!
❏ポイント
・実装中やプルリク作成前に必ずrubocopでエラーが出ないことを確認する
❏メリット
rubocopで同じようなことを注意されることがありますが、何回か注意されるとどのように修正するべきか自然にわかるようになるため、スキルアップにもつながりやすく、読みやすいコードを書くことができるようになります。
❏導入手順
1. 以下をGemfileに記載
gem 'rubocop'
gem 'rubocop-rails'
2. bundle install後、ターミナルで以下のコマンドを叩いて修正箇所を確認
$ rubocop
まとめ
記事を読んでいただきありがとうございました!
今回の内容の中で「自分のプロジェクトで課題がありそうだな」と思う方は、「モデルを太らせること」を念頭においてコードを書き進めてみてください!
また、その際には前回の記事「Railsのファットモデル 3つの対処法」を読んで、参考にしていただくといいと思います。