スライドショー

【Rails入門】Controllerでよく使われる機能を紹介!

みなさんはControllerを使いこなしていますか?

この記事では、Controllerの基本的な使いかたとして、以下のような内容を説明します。

・Controllerとは何か
・Controllerの作成方法は?
・Controllerでよく使われる機能は?
・Controllerはモジュール化できませんか?

Controllerには、ViewModelを統括するというもっとも重要な役割があります。

もっとも重要な役割を粛々と行うためにも、Controllerの基礎をしっかりと学び、ViewやModelとの連携をスムーズにできるようにしておきましょう。

Controllerとは

Controllerは、MVCを構成するコンポーネントの1つです。

MVCは、以下の3つのコンポーネント(構成要素)から構成されるデザインパターンです。

コンポーネント(構成要素)説明備考
Model(モデル)データベースを取り扱うデータベースへの格納方法は、Modelに隠ぺいする
View(ビュー)画面表示を取り扱う表示方法は、Viewに隠ぺいする
Controller(コントローラー)(ユーザーの入力を受けて)ModelとViewにアレコレ指示するデータベースへの格納方法や表示方法は知らない

Controllerはユーザーの意思を反映したHTTPリクエストを受け取り、ModelやViewと連携しながら、ユーザーに返すデータを決定する処理を担当します。

上の表のとおり、データの追加、削除、更新は、Modelを利用します。

Modelについては、以下の記事をご覧ください。

【Rails入門】モデル(model)の基本まとめ
更新日 : 2019年5月17日

Controllerの使いかたを理解するためにRuby on Railsをインストールする

Controllerの使いかたを理解するために、Ruby on Railsをインストールしておきましょう。

(1)Ruby on Railsをインストールします。

私は、以下の記事を参考に、VirtualBoxで作成した仮想パソコンにインストールしたLinux Mintに、Ruby on Railsの開発環境を作成しました。

基本的には記事の手順に従って操作しますが、app/samurai/sample1ディレクトリを作成する代わりに、app/samurai/controller-demoディレクトリを作成しました。

また、Ruby on Railsを起動して、ブラウザで画面が表示されることを確認したら、いったんRuby on Railsを終了してから次に進みます。

初心者でもかんたん!Ruby on Rails の開発環境の構築手順(Mac/Windows 両対応)
更新日 : 2019年8月9日

Linux Mintのインストールについては、以下の記事で詳しく説明しています。

Linux Mint Cinnamonエディションを使ってみよう
更新日 : 2019年12月5日

Controllerを作成する

では、Controllerを作成してみましょう。

Controller(+基本的なViewやルーティング)を作成するには、以下のコマンドを使用します。

bin/rails generate controller Controller名 アクション1 アクション2...

Controller名のあとに入力するアクションは複数指定できます。

ルーティングについては、以下の記事を参考にしてください。

【Rails入門】ルーティング (config/routes.rb)の書き方を説明!
更新日 : 2019年7月31日

では、実際にControllerを作成してみましょう。

(1)「端末」で以下のコマンドを入力します。

bin/rails generate controller Grapes action1 action2

実行結果:

Running via Spring preloader in process 18774
      create  app/controllers/grapes_controller.rb
       route  get 'grapes/action2'
       route  get 'grapes/action1'
      invoke  erb
      create    app/views/grapes
      create    app/views/grapes/action1.html.erb
      create    app/views/grapes/action2.html.erb
      invoke  test_unit
      create    test/controllers/grapes_controller_test.rb
      invoke  helper
      create    app/helpers/grapes_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/grapes.coffee
      invoke    scss
      create      app/assets/stylesheets/grapes.scss

作成されたファイルの用途は以下のとおりです。

ファイル名説明
app/controllers/grapes_controller.rbControllerファイル
config/routes.rbルーティングファイル
app/views/grapes/action1.html.erb
app/views/grapes/action2.html.erb
Viewファイル
test/controllers/grapes_controller_test.rbtest用ファイル
app/helpers/grapes_helper.rb独自helper設定用のファイル
app/assets/javascripts/grapes.coffeecoffeescript
app/assets/stylesheets/grapes.scssscss

※config/routes.rbは変更されます。

Controllerの命名規則について

Modelと結びつきがある場合は、Controller名をGrapesのように複数形にします。

Railsでは、使用するファイルなどを名前によって自動的に推測するため、命名規則に従っていないと予期しないエラーが発生してしまいます。

名前を正しく決める必要があり、それだけなら欠点のように思えますが、その代わりに冗長なコードが減るという利点があります。

Controllerを削除する

Controller(+基本的なViewやルーティング)を削除するには、以下のコマンドを使用します。

bin/rails destroy controller Controller名

では、実際にGrapesを削除してみましょう。

(1)「端末」で以下のコマンドを入力します。

bin/rails destroy controller Grapes

実行結果:

Running via Spring preloader in process 19022
      remove  app/controllers/grapes_controller.rb
      invoke  erb
      remove    app/views/grapes
      invoke  test_unit
      remove    test/controllers/grapes_controller_test.rb
      invoke  helper
      remove    app/helpers/grapes_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/grapes.coffee
      invoke    scss
      remove      app/assets/stylesheets/grapes.scss

rails generate controllerコマンドで作成されたファイルが削除されます。

ここで、config/routes.rbに設定されたルーティングの設定は残っていることに注意してください。

config/routes.rbには、他のControllerのアクションに関するルーティングも記述されているため、ファイルを削除すると問題になるためです。

そこで、config/routes.rbを編集して、Grapesに関するルーティングを削除しましょう

(2)config/routes.rbを編集します。

編集前:

Rails.application.routes.draw do
  get 'grapes/action1'

  get 'grapes/action2'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

編集後:

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

Controllerでよく使われる機能

次に、Controllerでよく使われる機能を紹介しましょう。

params

params[:id]のように書くと、Railsで送られてきた値(パラメータ)を受け取れます。

パラメータの受け渡しは、以下の記事を参考にしてください。

【Rails入門】params使い方まとめ
更新日 : 2019年7月31日

redirect_to

redirect_to action: :example1のように書くと、自動的なページの切り替え(次のアクションの呼び出し)を簡単に実装できます。

redirect_toの使いかたは、以下の記事を参考にしてください。

【Rails入門】redirect_toの使い方まとめ
更新日 : 2017年7月22日

flash

flash[:notice] = “任意のメッセージ”のように書くことで、任意のメッセージをViewに表示できます。

flashの使いかたは、以下の記事を参考にしてください。

【Rails入門】flashの使い方まとめ
更新日 : 2017年8月3日

render

render "help"と書くことで、help(app/views/pages/help.html.erb)テンプレートを表示できます。

renderの使いかたは、以下の記事を参考にしてください。

rails renderの基礎から使い方まで(partial, 引数)
更新日 : 2018年8月21日

ActiveSupport::Concernを使ってアクションをモジュール化する

一つのControllerにたくさんのアクションを記述しすぎると、コードが管理しにくくなったり、テストに時間がかかりすぎたりする問題が起きます。

そんなときは、ActiveSupport::Concernを使うことで、アクションをモジュール化できます。

Viewの場合は部分テンプレート(partial)を使って小分けにしますが、Controllerではモジュール化して小分けにします。

ここからは、実際にActiveSupport::Concernを使ってみましょう。

動作確認用のWebアプリは、scaffoldで作成します。

scaffoldについてわからない方は、以下の記事を参考にしてください。

【Rails入門】初めてのWebアプリ開発ならscaffoldが最短!
更新日 : 2018年8月21日

(1)「端末」で以下のコマンドを1行ずつ順番に入力します。

bin/rails generate scaffold Banana name:string
bin/rails db:migrate
bin/rails console

(2)以下のコードを入力します。

Banana.create(name:"キャベンディッシュ")
Banana.create(name:"ラカタン")
Banana.create(name:"レディ・フィンガー")
Banana.create(name:"シマバナナ")
Banana.create(name:"プランテン")
Banana.create(name:"グロスミッチェル")
Banana.create(name:"ハイランド")
exit

これで必要なファイルとデータが作成されました。

(3)以下のコマンドを入力します。

bin/rails server

scaffoldを使ってWebアプリを作成すると、ルート構成がRESTfulの考え方に従って作成されます。

app/controllers/bananas_controller.rb:

class BananasController < ApplicationController
  before_action :set_banana, only: [:show, :edit, :update, :destroy]

  # GET /bananas
  # GET /bananas.json
  def index
    @bananas = Banana.all
  end

  # GET /bananas/1
  # GET /bananas/1.json
  def show
  end

  # GET /bananas/new
  def new
    @banana = Banana.new
  end

  # GET /bananas/1/edit
  def edit
  end

  # POST /bananas
  # POST /bananas.json
  def create
    @banana = Banana.new(banana_params)

    respond_to do |format|
      if @banana.save
        format.html { redirect_to @banana, notice: 'Banana was successfully created.' }
        format.json { render :show, status: :created, location: @banana }
      else
        format.html { render :new }
        format.json { render json: @banana.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /bananas/1
  # PATCH/PUT /bananas/1.json
  def update
    respond_to do |format|
      if @banana.update(banana_params)
        format.html { redirect_to @banana, notice: 'Banana was successfully updated.' }
        format.json { render :show, status: :ok, location: @banana }
      else
        format.html { render :edit }
        format.json { render json: @banana.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /bananas/1
  # DELETE /bananas/1.json
  def destroy
    @banana.destroy
    respond_to do |format|
      format.html { redirect_to bananas_url, notice: 'Banana was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_banana
      @banana = Banana.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def banana_params
      params.require(:banana).permit(:name)
    end
end

今回はActiveSupport::Concernを使って、これらのアクションの一部を別のファイルに切り出してみましょう。

具体的には、app/controllers/concernsディレクトリにファイルを作成します。

(1)app/controllers/concerns/banana_one.rbを以下の内容で作成します。

module BananaOne
  extend ActiveSupport::Concern

  # GET /bananas
  # GET /bananas.json
  def index
    @bananas = Banana.all
  end

  # GET /bananas/1
  # GET /bananas/1.json
  def show
  end

  # GET /bananas/new
  def new
    @banana = Banana.new
  end

  # GET /bananas/1/edit
  def edit
  end
end

Railsらしく、module名は、頭文字大文字、単語の境界に「_」無しで、ファイル名は、頭文字小文字、単語の境界に「_」有りという命名規則があります。

上の例のように、module名をBananaOneにした場合は、ファイル名はbanana_one.rbにします。

この命名規則に従っていないと、ActiveSupport::Concernが適切に読み込めません。

(2)app/controllers/bananas_controller.rbを以下のように修正します。

変更後:

class BananasController < ApplicationController
  before_action :set_banana, only: [:show, :edit, :update, :destroy]

  include BananaOne

  # POST /bananas
  # POST /bananas.json
  def create
    @banana = Banana.new(banana_params)

    respond_to do |format|
      if @banana.save
        format.html { redirect_to @banana, notice: 'Banana was successfully created.' }
        format.json { render :show, status: :created, location: @banana }
      else
        format.html { render :new }
        format.json { render json: @banana.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /bananas/1
  # PATCH/PUT /bananas/1.json
  def update
    respond_to do |format|
      if @banana.update(banana_params)
        format.html { redirect_to @banana, notice: 'Banana was successfully updated.' }
        format.json { render :show, status: :ok, location: @banana }
      else
        format.html { render :edit }
        format.json { render json: @banana.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /bananas/1
  # DELETE /bananas/1.json
  def destroy
    @banana.destroy
    respond_to do |format|
      format.html { redirect_to bananas_url, notice: 'Banana was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_banana
      @banana = Banana.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def banana_params
      params.require(:banana).permit(:name)
    end
end

(3)ブラウザで「http://localhost:3000/bananas」にアクセスします。

ActiveSupport::Concernでモジュール化したindexアクションもしっかり呼び出されていますね。

同様に、以下のURLにアクセスして、各アクションが呼び出せることを確認してみてください。

  • http://localhost:3000/bananas/1(showアクション)
  • http://localhost:3000/bananas/new(newアクション)
  • http://localhost:3000/bananas/1/edit(editアクション)

このように、include BananaOneで、app/controllers/concerns/banana_one.rbの内容を読み込み、モジュール化する前と同様に呼び出せるのです。

なお、モジュール化したBananaOneは、別のControllerからも呼び出せるため、共通のアクションが複数のControllerに存在する場合にも活用できます。

respond_toを使ってJSONやXMLを取得する

respond_toを使うと、URLにあわせて表示するフォーマットを切り替えられます。

具体的には、以下のようなコードで、htmlとJSONとXMLを切り替えられるようになります。

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
    respond_to do |format|
      format.html
      format.json {render :json => @posts}
      format.xml  {render :xml => @posts}
    end
  end
(省略)

respond_toの使いかたは、以下の記事で詳しく説明していますので、ぜひご覧ください。

rails renderの基礎から使い方まで(partial, 引数)
更新日 : 2018年8月21日

まとめ

この記事では、Controllerの使いかたを説明しました。

作成方法と命名規則さえわかっていればControllerを作成できますが、このページで紹介したような機能をしっかりマスターしておけば、Webアプリを開発するときに必要な基本的な機能はカバーできるでしょう。

また、実装していく段階で、ファイルが大きくなりすぎたと思ったらActiveSupport::Concernを活用したモジュール化を検討してはいかがでしょうか。

LINEで送る
Pocket

無料でSEからWebエンジニアへ転職しませんか?



侍エンジニア塾では、完全未経験の方から現在SEだけどプログラミングはやっていないという経験者まで、幅広い方々の人生を好転させるプログラミング指導を行ってきました。SEの方とお話していくなかで、

  • システムエンジニアという職業だけどコードが書けない
  • 事務作業が多くスキルがないため将来が不安
  • スクールに通うと完全未経験者と同じスタートになるからレベルが合わない
という、すでに知識があるSEならではのお悩みがあることに気づきました。そんな方におすすめなのが、弊社の「転職コース 」です。

弊社では、マンツーマンでレッスンを行いますので、現在お持ちの知識レベルからカリキュラムを作成いたします。さらにこちらの転職コースは無料で受講を始められて転職成功でそのまま卒業できるというとてもお得なコースとなっています。

既に知識のあるSEといっても転職は年齢が若いほど受かりやすいため、まずは無料体験レッスンで今の現状や理想の働き方について一緒に考えていきましょう。

まずは無料体験レッスンを予約する

書いた人

侍テック編集部

侍テック編集部

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説