ボクココ

個人開発に関するテックブログ

Rails のコードをきれいに保つために気をつけたい、たった一つのこと

ども、@kimihom です。今回は Rails のお話。

割と初心者が Rails を使ってサービスを作ると、 Fat Controller (コントローラーにコードを大量に書く) ということをしがち。んじゃあ どうやったらそうならないように済むかを簡単に説明しようと思う。

Fat Controller がイケてない理由

この話をする前に、そもそもなぜ Fat Controller がイケてないのかを説明する。

シンプルに言うと、 MVC になっていないからだ。 Controller ってのは基本的に受け取ったリクエストを Model に渡し、最終的に View にデータを渡すということをやる。Modelをコントロールし、Viewに渡すのが Controller だ。 "でも Model ってのは ActiveRecord だから DB のデータ操作したい時だけ使うんでしょ?" と勘違いしがちなのが Rails の罠だ。Model に DB操作だけをさせるように書いてしまうと、 Controller の負担が増え、見事な Fat Controller が出来上がる。

Fat Controller が発生すると、同じような処理が出てきた時に ApplicationController にコードを書くようになるだろう。そうしたら悪夢の始まりだ。どこで呼ばれているのかも把握できない大量のメソッドが ApplicationController を覆うだろう。実際に私が仕事の現場で Fat な ApplicationController を見たことがあるが、いやはや Rails なのにプログラミングが楽しくなかったね。

しっかりと Model にコードを書くようになると、ユニットテストがとても容易になる。これがとても大事なメリットだ。 TDD をやれとは私は言わないが、少なくとも ユニットテストはしっかり書くコードを書くことを推奨する。Model におけるユニットテストは基本的にはロジックとDB処理の確認になるのでシンプルになりやすい。これを Controller にロジックをまとめると、リクエスト/レスポンスのテストの他に ロジックのテストまで書かないといけなくなるので Controller のテストが大変になる。Model がきれいになれば、 Controller がきれいになり、 View がきれいになる。そして JavaScript がきれいになり、 CSS/HTML もきれいになるのだ!

Fat Controller になる原因

割と画面設計がうまくいってないと Fat Controller になりがちなのよね。具体的には 1つの画面にたくさんの Model を扱うような画面を作る時に頻発する。 Facebook を例にとると、左にユーザープロフィールとメニューがあり、真ん中に投稿があり、右にユーザーのリアルタイム情報がある。

そこで何も考えずにただ Controller に全部書いちゃえ!ってすると悪しき習慣がサービスが終わるまで残り続ける。その Rails コードをメンテするのは至難の技だ。

Fat Controller を防ぐために

さて前置きが長くなったが、本題に移る。

まず最も大事な画面設計からだ。先ほどの Facebook の例だと、まずは Rails の View を読み込むベースとなる Controller を作成する。この Controller でシンプルに HTML を返すようにする。後は全て JavaScript の Ajax で View を当て込むようにしよう。その Ajax の呼び先として、個別に ProfileController, MenusController, PostsController, FriendsController などを定義しよう。

f:id:cevid_cpp:20160331200700p:plain

BaseController のロードが完了したら、 それぞれの Controller を呼ぶために Ajax でリクエストを送る。MenusController, PostsController, FriendsController は REST API 形式にし、 HTML か JSON を返すようにし、レスポンスを受け取った JavaScript 側で UI の更新を行う。

このような作りにすると、フロントは AngularJS や React.js などがいいのかって感じになるけど、 underscode.js などを使うか、素の jQuery でも Ajax のレスポスに HTML(.erb) を返せば問題なく処理を書ける。個人的には HTML(.erb) をそのまま返すようにすれば、 Rails のあらゆる ヘルパメソッドが使えるので、好んで使っている。

Rails だと アセットパイプラインで最初の BaseController で一気に JavaScript をまとめて読み込むようになるので、そこに気をつけてコーディングしよう。できる限り html.erb内で JavaScript を書かないようにしたほうがいい。HTML 内に JavaScript を書くとアセットパイプラインによる関数名の圧縮を受けないため、関数の呼び出しとかで困ることが出てくるためだ。

とにかく Controller は RESTful 形式で考えること 。 RESTful は データの表示、作成、編集、削除の一塊の Controller だ。それ以外の例外をなるべく作らないようにすることが 美しい Rails コードを保つための一つの秘訣である。初めのうちは慣れないかもしれない。てことで例えば他サービスの REST API などを触ってみるといい勉強になると思う。こうやって URL を作るのかーって勉強になるだろう。

その上で、Model にロジックまで書くこと。関連する複数の Model を Controller でうまく命令してあげるようにコードを書くようにしよう。モデル間で共通の処理が出てきた場合は concern モジュールを定義して include すればいい。 そしてユニットテストをちゃんと書くように心がけよう。Controller にはほとんどコードを書かないようにするよう、 意識してプログラミングしよう。

この方法は、どうしても最初のリクエストで全てが完了するわけではないので、あまり好ましく思わない人(技術のわからないプロデューサー)もいるだろう。そういう場合は cells などを使うといいのかもしれない。自分は使ったことないのでなんとも言えないが。

終わりに

今回は Rails における FatController を防ぐためのポイントを紹介した。この方法をうまく実践すればきっとあなたの Rails コードは美しくメンテナブルになると思う。 JavaScript や Stylesheet などがなぜ app/assets/ 以下に コントローラ毎に作成される のかもちゃんと理解できるようになると思う。 Rails はもともと Restful になるよう設計されてフレームワーク化されている。 しっかりと Rails の"レール"に乗るには、 しっかりとした URL や 画面設計が必要だ。

FatController で悩まされる Rails エンジニアが少なくなれば幸いだ。

最後にこの方法以外に FatController を防ぎ RESTful でうまくできる方法があればぜひシェアしていただきたい。