ブラウザからアプリにアクセスしたときの処理の流れ
書籍管理のアプリケーションのhttp://localhost:3000/books/1
にアクセスする(GETリクエスト)
books/1
のパスにマッチするルーティングを探す
ルーティングファイルのbooks/1
へアクセスするルーティング
GETリクエストのbooks/1
のパスならbooksコントローラのshowアクションを参照する
Rails.application.routes.draw do
get "books/:id" => "books#show"
end
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というフォーマットを指定しているのがわかります。
コントローラではURLのパスとルーティングから導かれたアクションの中で、モデルなどを通じて必要なデータを取得し加工します。
最後にそのデータをビューに渡してレンダリングを指示することで、Webアプリケーションの画面をユーザーに返す役割を担っている。
アクションの前後に処理を差し込むことができるコールバック処理のようなもの。フィルターとも呼びます。フックの種類は三種類。(before_action
、after_action
、around_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]