Rails初学者によるRailsチュートリアル学習記録⑤ 第3章

#目次
- [1. はじめに](#1-はじめに)
- [2. 第3章の概要](#2-第3章の概要)
- [3. 学習内容](#3-学習内容)
- [4. 終わりに](#4-終わりに)

#1. はじめに
- この記事は、Rails初学者の工業大学三年生がRailsチュートリアルの学習記録を<br>つけるための記事です。
- 筆者自体がRailsやWebについて知識が少ないので、内容の解釈などに<br>間違いがある可能性があります。(その時はコメントで指摘してくださると助かります！)
- Railsチュートリアル内ではRailsの内容以外にも、gitでのバージョン管理やHerokuを使ったデプロイも<br>学習しますが、gitに関しては既に私が学習済みのため学習記録には記述しません。
- 演習の記録も省略します。

#2. 第3章の概要
第3章からは本格的なサンプルアプリケーションを1から開発していきます。
まずは静的なページを自分で作成して少しずつ動的なコンテンツを追加という流れです。
この章ではほんの少しの動的なコンテンツを追加して、プログラミングに必要な自動化テストを学んでいきます。

1. ほぼ静的なページの作成
    1. コントローラの生成
    1. テスト駆動開発
    1. テストコードの書き方
1. コードのリファクタリング
    1. リファクタリングとは
    1. HTMLファイルの内容のテスト
    1. HTMLにRubyを埋め込む

#3. 学習内容
###1. ほぼ静的なページの作成
####1-1. コントローラの生成
###### ①コントローラを生成するコマンド
静的なページの作成に必要なコントローラは、scaffoldでも使用したrails generateコマンドを使用します。
今回はコントローラ名を「StaticPages」に設定して、Homeページ、Helpページ、Aboutページ、という3つのページを作成します。
つまりそれに対応するアクションをStaticPagesコントローラを作成するということです。
そのためのコマンドは`rails generate controller StaticPages home help`です。
このコマンドではaboutアクションは作成されませんが、aboutアクションはコマンドを使わず1から作成していきます。

###### ②生成されるページ
コントローラを作成した段階でルーティングが設定されるので、そのURLにアクセスすればページが表示されます。
今回は以下のようなルーティングと、アクション、ビューが設定されています。

```ruby:config/routes.rb
Rails.application.routes.draw do
  get 'static_pages/home' #homeアクションのURL
  get 'static_pages/help' #helpアクションのURL
  root 'application#hello'
end
```

```ruby:app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home #homeアクション
  end
  def help #helpアクション
  end
end
```

![:/static_pages/home にアクセスした結果](https://railstutorial.jp/chapters/images/figures/raw_home_view_3rd_edition.png)
>出典 https://railstutorial.jp/chapters/static_pages?version=5.1

####1-2. テスト駆動開発
サンプルアプリでは変更を行う際に、自動化テストも同時に作成して機能が正しく実装されているかを確認するようにします。
テストコードを書くタイミングには変更の内容や、テストを作成する開発者の技量によって変わりますが、
大きく分けて以下の2つのタイミングでテストコードを書きます。
「テストコードを先に書いてからアプリの変更を行う」
「アプリの変更を行ってからテストコードを書く」
この2つのタイミングの内、テストコードを先に書く方法をテスト駆動開発と呼びます。
テスト駆動開発は開発に慣れてくると扱えるようになるのですが、Railsチュートリアルでも必要に応じてテスト駆動開発を採用しています。

####1-3. テストコードの書き方
###### ①デフォルトのテストコード
テストコードはコントローラ作成用のコマンドを実行時に、テストファイルが作成されるのでそこにテスト内容を記述していきます。
以下のコードはStaticPaagesコントローラのデフォルトのテストです。

```ruby:test/app/controllers/static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
  end
end
```
この2つのテストは、それぞれhomeページとhelpページがリクエストに対して正常にレスポンスを返すかをテストするコードです。
`get static_pages_home_url`で指定したURLにgetリクエストを送っていて、
`assert_response :success`でレスポンスが成功になっているかを確かめています。

###### ②テスト駆動開発をやってみる
ここからは、aboutアクションをテスト駆動開発で作成していきます。
まずは、homeアクションとhelpアクションと同じ内容のテストを作成します。

```ruby:test/app/controllers/static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end
end
```
テストコードを追記してテストを実行すると
`$ rails test
NameError: undefined local variable or method static_pages_about_url'`
上記のようにエラーが返ってきます。
これはaboutページへのURLが見つからないというエラーなので、ルーティングファイルにURLを追加すると解消されます。
追記した後、またテストを実行すると以下のエラーが返ってきます。
`$ rails test
AbstractController::ActionNotFound:
The action 'about' could not be found for StaticPagesController'`
このエラーはaboutアクションがコントローラーにないというエラーです。
これはコントローラにaboutアクションを追記すれば解消されます。
またテストを実行すると、
`$ rails test
ActionController::UnknownFormat: StaticPagesController#about
is missing a template for this request format and variant.`
このようなエラーが返ってきます。
このエラーはビューファイルがないため発生しています。
よって、about.html.erbというビューファイルを作成して内容を記述するとこのエラーは解消されます。
もう一度テストを実行するとテストは成功となります。
`$ rails test
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips`

###2. コードのリファクタリング
####2-1. リファクタリングとは
リファクタリングとはプログラムの動作を変えずに、
コードの構造を変更して動作速度を速めたり、可読性を高めたりといった改善を行うことです。
####2-2. HTMLファイル内容のテスト
###### ①リファクタリングの内容
今回のリファクタリングはビューファイルのタイトルタグの内容をページごとに自動で変更されるようにします。
この変更もテスト駆動開発で行っていくため、まずテストを作成していきます。

###### ②タイトルをテストする
このテストではtitleタグに指定した文字列が入っているかをテストします。
以下のコードがhomeビューのtitleタグの内容が、
「"Home | Ruby on Rails Tutorial Sample App」となっているかを確かめるテストです。

```ruby:test/app/controllers/static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App" #タイトルタグのテスト
  end
```
上記のコードの`assert_select "title", "Home | Ruby on Rails Tutorial Sample App"`の部分で
titleタグの内容を確認しています。
第一引数が内容を確認したいタグを指定していて、第二引数が存在しているか確かめたい内容です。
このようなテストを他のページにも同様に書きます。

####2-3. HTMLにRubyを埋め込む
リファクタリングで実装したいページごとに自動でタイトルが変わるようにする変更は、
HTMLにRubyを埋め込むことで実装していく。
以下のコードが埋め込みRubyによってタイトルが自動的に変更されるようになったビューです。

```html:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
      <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> 
      <%= 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>
```
このファイルはビューファイルのheadタグ等の共通部分を記述して、`<%= yield %>`の部分で各ページの内容を挿入します。
これによって各ビューファイルの共通部分を一箇所にまとめています。
titleタグの下の4行はRailsが作成してくれるJavascriptを扱えるようにするためのコードや、
クロスサイトスクリプティング攻撃の対策用のコード等です。
titleタグの中の`<%= yield(:title) %>`で各ページのタイトルを自動的に挿入しています。
これは各ビューファイルで`<% provide(:title, "Home") %>`のように記述することで第一引数でラベルを定義して、
第二引数で値を入力することで、その値を受け取って挿入してくれるコードです。
この2つのコードによって、各ビューファイルごとに入力されたタイトルが挿入されて、タイトルが自動的に変更されるようになります。


#4. 終わりに
第三章から、本格的なWebアプリケーションの開発が始まりました。
内容もこれまでの2つの章と比べると濃くなっており、記事の内容も大分長くなってしまいました。
これでも端折ったほうなのですが、記事の作成が大変です:(
テストやリファクタリングといった、Progateなどでは触れてこなかった内容が出てきましたが、
難易度としてはまだ躓くほどではないので、内容が難しくなってくる前に記事の作成に慣れることができればと思います。