ブラウザからアプリにアクセスしたときの処理の流れ

  1. 書籍管理のアプリケーションのhttp://localhost:3000/books/1にアクセスする(GETリクエスト)

  2. books/1のパスにマッチするルーティングを探す

    ルーティングファイルのbooks/1へアクセスするルーティング

    GETリクエストのbooks/1のパスならbooksコントローラのshowアクションを参照する

    Rails.application.routes.draw do
      get "books/:id" => "books#show"
    end
    
  3. booksコントローラを作成して、showメソッド(アクション)を作成します。showアクションでは本の情報を取得してインスタンス変数に代入しています。

    Sayo-MacBook-Pro:book_admin SAYO$ bin/rails g controller books
    Running via Spring preloader in process 85902
          create  app/controllers/books_controller.rb
          invoke  erb
          create    app/views/books
          invoke  test_unit
          create    test/controllers/books_controller_test.rb
          invoke  helper
          create    app/helpers/books_helper.rb
          invoke    test_unit
          invoke  assets
          invoke    scss
          create      app/assets/stylesheets/books.scss
    
    class BooksController < ApplicationController
      def show
        @book = Book.find(params[:id])
        respond_to do |format|
          format.html
          format.json
        end
      end
    end
    

    @book = Book.find(params[:id])ここのparams[:id]でパス情報に埋め込まれた:idの部分、ここでは1を取得することができます。

    paramsオブジェクトにはルーティングで定義したパラメータ部分(上記のような例)以外にもPOSTで送信したパラメータやURLのクエリストリングの値も取得できます。リクエストデータとして送られてくる値はparamsオブジェクトを通して取得できるということです。

    クエリストリングは、Webブラウザがサーバにデータを送信する際に必要な表記です。URLの途中に「?」記号があれば、「?」以降の文字列はクエリストリングとなります。

    BooksController < ApplicationControllerの部分でApplicationContorollerを継承していることがわかります。

    ApplicationControllerはアプリケーションの全てのコントローラで共通するヘルパーメソッドや属性、挙動などを定義する場所です。実際にアプリを作成したときは全てのアクションの実行前にログインしているの確認するというメソッドをこのファイルに定義していました。

    ApplicationController < ActionController::BaseをみるとActionController::Baseを継承しているのがわかります。これはRailsで提供されているコントローラの基底クラスです。railsのコントローラが持つべき基本機能を提供しています。

    ビューに対する指示です。このように記述することでユーザーのリクエストに応じて二種類のフォーマットでビューのレンダリングを行えるようになります。実際にどのフォーマットのレスポンスを返すかはリクエストヘッダーやURLの拡張子などによって決まります。

    respond_to do |format|
    	format.html
    	format.json
    end
    

    PFで作成したアプリのトップページアクセスした時のリクエストヘッダーを確認してみました。text/htmlというフォーマットを指定しているのがわかります。

    https://i.gyazo.com/84048ac32670a14b5015d8125eb33163.png

  4. コントローラではURLのパスとルーティングから導かれたアクションの中で、モデルなどを通じて必要なデータを取得し加工します。

  5. 最後にそのデータをビューに渡してレンダリングを指示することで、Webアプリケーションの画面をユーザーに返す役割を担っている。

フック

アクションの前後に処理を差し込むことができるコールバック処理のようなもの。フィルターとも呼びます。フックの種類は三種類。(before_actionafter_actionaround_action

ここではset_bookメソッドを定義して、showとdestroyアクションの処理前に実行するようにしています。

class BooksController < ApplicationController
  protect_from_forgery except: [:destroy]

	# フック
	# onlyは指定したアクション、exceptは指定したアクション以外
  before_action :set_book, only: [:show, :destroy]

  def show
    respond_to do |format|
      format.html
      format.json
    end
  end

  def destroy
    @book.destroy
    respond_to do |format|
      format.html { redirect_to "/"}
      format.json { head :no_content }
    end
  end

  private

  def set_book
    @book = Book.find(params[:id])
  end
end

aroundフックはアクションの前後で呼び出すメソッドではbefore相当の処理を実行したあと、yieldを使ってアクション側に処理を戻してあげる必要があります。

class BooksController < ApplicationController
  around_action :action_logger, only: [:destroy]

  private

  def action_logger
		# destroyアクションの実行前の処理
    logger.info "around-before"
    yield
		# destroyアクションの実行後の処理
    logger.info "around-after"
  end
end

フックのスキップも可能です。よく使われるのがログインが必要なアプリケーションを構築する時です。親コントローラであるapplicationコントローラで定義したrequire_loginメソッドを子コントローラでこのフックをスキップできます。

class ApplicationController < ActionController::Base
  before_action :require_login

  def require_login
  end
end

スキップするときはこのように記述します。

skip_before_action :require_login, only: [:new, :create]