

Ruby on
Railsでwebアプリを作っているのですが、コントローラーの記述が長くなってしまった場合、どのようにファイルを分割するのがいいのでしょうか？

今は、コマンドから新しくコントローラーを作って

[code]

    class HogeController < ApplicationController
    
[/code]

という形になっているやつにソースを移しているんですが、

<http://qiita.com/aDaichiOta/items/3fa5bc302565bcd495a8>

ここにあるみたいに

[code]

    class HogeController < BaseController
    
[/code]

としたほうがいいのでしょうか？

その場合ってコマンドからではなく直接rbを新規作成したほうがいいのですかね？
コマンドから作るとviewsの下にフォルダ掘られちゃったりしているのですが・・・。

補足として、 MVCの扱いは

<http://at-grandpa.hatenablog.jp/entry/2013/11/01/072636>

ここにあるあるやつの「勘違い形式」でお願いします。
あと、趣味でやっているものなので、厳密な事は求めていません。あくまで一般的に、みんなはどうやっているのかな？というところで回答をお願い致します。


CC BY-SA 3.0
2014-12-05T10:45:05.293
371
2014-12-07T01:33:05.410
2014-12-05T14:40:46.490
30
705
question
ruby-on-rails mvc
Railsでコントローラーの記述を分割する方法


BaseController を作成してそちらに移動するのは、おそらく良いアイデアではないでしょう。 Hoge の代わりに Base
が大きくなるオチがチラつきます。一般に継承は Hoge **IS A** Base という関係が成立するときにのみ、行うべきです。

原則は **適切に責務を分割する** です。
([Railsでサービスとフォームを導入してみる話](http://a-suenami.hatenablog.com/entry/2013/12/06/092146)より引用)

ご自身の別の [質問](https://ja.stackoverflow.com/questions/372/ruby-on-
rails%E3%81%A7%E6%9C%AC%E5%BD%93%E3%81%AEmvc%E3%81%AE%E5%AE%9F%E8%A3%85%E6%96%B9%E6%B3%95)
にもあるように、移せるものはモデルへ移すか、上記のエントリーにあるサービスやフォームを導入するということを検討してみてはどうでしょうか。


CC BY-SA 3.0
2014-12-05T13:49:12.370
380
2014-12-07T01:33:05.410
2017-04-13T12:52:39.113
-1
208
371
answer


別のアプローチとして、Controllerが肥大化する要因として「複数のRequestに対する処理を1つのController内で行っている」ことも考えられます。例えばRESTfulな設計を適用した場合、あるリソースに対する操作（CRUD）を1つのController内で定義することが一般的です。つまり、最低でもRequestを受け取るためのメソッドがCRUDに対応して4つ存在します。それぞれのメソッド内の処理が大きくなればなるほど、そのControllerは肥大化していくわけです。

もしその状態になっているのであれば、config/routes.rbを書き換えて、CRUDそれぞれに一つずつ別のControllerを作成する、という対応もありだと思います。これであれば、各Controllerの内容が単純計算で4分の1に減らせる可能性が出てきます。

そうではなく、1つのRequestに対する処理が肥大化している場合は、上の回答にあるような対策が必要でしょうね。


CC BY-SA 3.0
2014-12-05T14:36:36.443
383
2014-12-05T14:36:36.443
531
371
answer


私も Rails 3.2 系で、BaseController を作り共通の処理を書きましたが、結局肥大化してしまい見通しが悪くなってしまいました。

そこで、Model 等でも利用している
[Concerns](http://elegantbrew.tumblr.com/post/70990048275/controller-concerns-
in-rails-4) という部品に分解し、必要な場合に追加を行うようにしました。

例えば、以下の様に JSON 出力が必要な例外のハンドリングを Concerns にして注入しました。

[code]

    module ExceptionHandler
      extend ActiveSupport::Concern
    
      included do
        rescue_from Errors::BadRequest,  with: :bad_request
      end
    
      protected
      def bad_request(exception)
        render_exception status: __method__, debug_message: [exception.message,    exception.backtrace].join("\n")
      end
    
      def render_exception(args)
        status = args[:status].to_sym
    
        error_message = {
          status_code: Rack::Utils.status_code(status),
          status: status.to_s.humanize,
          message: args[:message] }
    
        respond_to do |format|
          format.json { render json: error_message, status: status }
        end
      end
    end
    
[/code]

独自の構造を作るときには基本的に Scaffold や Generator は利用しませんが、`rails generate controller
MyContoroller`コマンドで生成を行っている場合、いくつかのオプションを付与することで生成物をスキップすることが出来ます。

[code]

    --skip-template-engine (--no-template-engine) # View の生成をスキップする
    
[/code]


CC BY-SA 3.0
2014-12-05T19:31:25.573
387
2014-12-06T06:00:03.453
2014-12-06T06:00:03.453
745
745
371
answer


一概にこの方法が良いとは言い切れないと思います。対象の状況依存ではないでしょうか。

かつて、私がやったことがある方法をあげると、以下の二つです:

  * コントローラでの共通部分をベースクラスに括りだして、複数のコントローラで共有する

  * コントローラで複数のモデルを操作するコードを、データを伴わないモデルとして独立させて、そこに集約し、コントローラから呼ぶ形にし、コントローラのコードを減らす

前者は、操作するモデルが複数で親子関係があり、その親にも子にも、あるいは複数の子に対しての類似した操作の場合、有効なアプローチだと思います。

後者は、複数モデルに跨いだ操作をコントローラで多くしている場合に有効です。

一方、モデルがある程度の大きさを持っていて、ユニークな操作が多い場合は、コントローラの部分に含まれるコードが増えるのは避けがたいと思います。

また、一つ気をつけたいのは、コントローラは中(当該アプリのモデルモデル)と外(ユーザや外部システム）との仲立ちをするので、制約があり、実装はどうしても縛られるという点です。この手の議論をすると、モデルのデザインが悪い、という意見が出るものですが、コントローラは、UIとは限らず、内部のモデルと外部のモデルとのインターフェースとしての役割もありますから、きれい事ばかり言えないことはあると思います。たとえば、どんなに内部のモデルがシンプルにできていても、ある程度複雑な出力をせざるえないというのはあります。

なので、見やすさと、コードの共有の程度などを勘案しながら、上記のような方法のうちから、選択してゆくしかないのではないでしょうか。

Concerns も上手に使うと良い仕掛けだと思います。ただ、コードの場所が結構離れるので、わりと見通しわるくなってしまいます。


CC BY-SA 3.0
2014-12-06T08:57:38.473
398
2014-12-06T08:57:38.473
44
371
answer