👏

railsアプリケーションはどのように動いているのか?

2021/01/24に公開

前回の記事ではrailsのscaffoldコマンドを利用して、実際に動く画面を作成しました。

しかし、画面が動くのを見せただけでrailsがどのような流れで処理を行っているのかについては、まだ説明していません。

なので、今回の記事では「railsがリクエストからレスポンスまでどのような仕組みで動いているのか?」について解説していきます。

リクエストからレスポンスまでの流れ

railsaアプリケーションが「リクエストを受け取って」から「レスポンスを返す」までの流れは以下のようになっています。

  1. サーバーはリクエストを受け取る
  2. ルーティング機能により、URLに対応したコントローラーのアクションを呼び出す
  3. アクション内でデータ操作を必要とする際、モデルを呼び出す
  4. モデルからデータベースにアクセスしてデータのCRUDを行う
  5. アクションに対応したビューテンプレートを呼び出しHTMLを作成する
  6. 作成したHTMLをクライアントに返却する

ルーティング

たとえば、 http://localhost:3000/usersにアクセスした場合、routes.rbを読み込んでURLに対応したコントローラーのアクションを呼び出します。

アクションとは、「リクエストに対してどのような処理を行うのか?」を定義したメソッドのことです。

routes.rb

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

resources :users では基本的な機能を持つ7つのルーティングが自動で作成されます。

resourcesのルーティング機能

HTTPメソッド URL アクション 機能
GET /users index 一覧表示
GET /users/:id show 詳細表示
GET /users/new new 新規登録画面
POST /users create 登録処理
GET users/:id/edit edit 編集画面
PUT users/:id update 更新処理
DELETE users/:id destroy 削除処理

この表を見るとGETでhttp:localhost:3000/usersにアクセスするとUserコントローラーのindexアクションが呼ばれることが分かりますよね。

コントローラー

では、実際にuserコントローラーのindexアクションを見ていきましょう。

users_controller.rb

def index
    @users = User.all
  end

indexアクションではUserモデルを使ってUser情報を全て取得しています。コントローラーで定義したインスタンス変数はビューで参照が可能です。

モデル

indexアクションでUserモデルが呼び出されているのでuser.rbを見てみましょう。

user.rb

class User < ApplicationRecord
end

UserモデルはApplicationRecordを継承しているだけで中身には何も記述されていません。

なぜモデルはDB操作メソッドを使えるのか?

なぜUserモデルでallメソッドが使えるのかというとApplicationRecordから継承されているからです。

このApplicationRecordにはデータベース操作関連のメソッドが多く用意されています。具体的にDB操作のメソッドには以下のようなものがあります。

  • create :データ作成
  • update :データ更新
  • destroy :データ削除
  • find :データ取得

ビュー

コントローラーで対象のデータをDBから取得すると次はビューの登場です。

ビューはHTMLをベースに動的なデータを埋め込むことからテンプレートファイルと呼ばれます。

デフォルトだと、「app/views/コントローラー名/アクション名.html.erb」のテンプレートファイルを呼び出します。なので、usersコントローラーのindexアクションだと app/views/users/index.html.erb が対象のテンプレートファイルです。

index.html.erb

<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @users.each do |user| %>
      <tr>
        <td><%= user.name %></td>
        <td><%= link_to 'Show', user %></td>
        <td><%= link_to 'Edit', edit_user_path(user) %></td>
        <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<br>

<%= link_to 'New User', new_user_path %>

このテンプレートファイルでは何をしているのかというとコントローラーで取得したuserの一覧 @users を全て表示して、「詳細画面、編集画面、削除処理のリンク」を出力しています。

ERBファイルとは?

railsで動的ファイルを作るにはデフォルトだとERBというテンプレートエンジンを使います。

テンプレートエンジンとは、HTMLの雛形と動的な処理から最終的なHTMLを生成する仕組みのことで、ERBでは <% ~ %><%= ~ %> を使って動的な処理を埋め込んでいます。

railsでは、ERB以外のテンプレートエンジンだと以下の2つが有名です。

  • halm
  • slim

どちらもERBよりも短く書けるのがメリットですが、その分HTML形式から離れるので学習コストが増えます。

ERBファイルの書き方

ERB以外のテンプレートエンジンの話はさておき、ERBファイルの<% ~ %> ではRubyでの処理を記述できます。たとえば、 <% @users.each do |user| %> では、コントローラーで取得したuser一覧のループ処理を行っています。

一方、 <%= ~ %> では、Rubyの変数を出力することが可能です。たとえば、ユーザー名を表示するために <%= user.name %> を使って動的にHTMLに出力しています。

ヘルパーメソッド

ビューではlink_toedit_user_pathなどメソッドを呼び出すだけで便利機能を利用できます。このメソッドをヘルパーメソッドと呼びます。

link_toメソッドは引数からaタグのリンクを作成します。

  • 第1引数:リンクに設定するテキスト
  • 第2引数:リンク先のURL
  • 第3引数:オプション

たとえば、詳細画面へ遷移するリンクは link_to 'Show', user で作成され、HTMLには <a href="/users/1">Show</a> で出力されます。

また、削除処理を行うlink_toメソッドでは第3引数も設定され、 method: :delete でHTTPメソッドをdeleteに設定、 data: { confirm: 'Are you sure?' } でdata属性を出力しています。

<a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/users/2">Destroy</a>

edit_(コントローラー名)_pathメソッド

edit_(コントローラー名)_pathメソッドで対象データの編集画面に遷移するURLを返します。今回はuserコントローラーを使っているため、edit_user_pathになっている。もし、コントローラー名がtaskならば、edit_task_pathで使用可能です。

ちなみに今回の編集画面へのリンクで、実際にHTMLとして出力されるURLは <a href="/users/2/edit">Edit</a> になります。

共通レイアウト

index.html.erbで出力している部分はHTMLの一部です。htmlタグやheadタグ、bodyタグなどは「application.html.erb」に定義されています。
application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Myapp</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

このapplication.html.erbが読み込まれ、<%= yield %>が個別のテンプレートファイルが出力する部分になります。

そのため、application.html.erbでは、アプリ全体の共通部分であるヘッダーやフッターなども設定することが多いです。

Discussion