railsチュートリアル第３章 埋め込みruby

##少しだけ動的なページ
今度はそれをほんの少しだけ動的にしてみましょう。
ページの内容に応じて、ページのタイトルを自ら書き換えて表示するようにします
ここでの目標は、Homeページ、Helpページ、Aboutページをそれぞれ編集し、最終的にページごとに異なるタイトルを表示することです
ビューの<title>タグの内容を変更
本節の終わりまでに、3つの静的ページのタイトルを「<ページ名> | Ruby on Rails Tutorial Sample App」という形式に変更します
レイアウトファイルを活用する。
ブラウザウィンドウの上部にウィンドウタイトルを変えるらしい。

一時的にファイル名を変更

```
mv app/views/layouts/application.html.erb layout_file
```

###タイトルをテストする（Red）

```rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    # getはGETリクエストで受け付ける普通のWebページを示す
    # GETを受け付けるよね？
    assert_response :success
    # response:successはリクエストが成功し、レスポンスとともに要求に応じた情報が返される
    # GETリクエストが成功、ページが表示されたらいい。
    # response:successは、実際にはHTTPのステータスコード200 OKを指す
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
    # assert_selectメソッドは、特定のHTMLタグが存在する確認
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end
  
  test "should get about" do
    get static_pages_about_url
    # aboutページを表示させる（GETリクエスト）
    assert_response :success
    # GETリクエストが成功したかを確認
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end

end
```

```
ubuntu:~/environment/sample_app (static-pages) $ rails t
Running via Spring preloader in process 21395
Run options: --seed 37847

# Running:

F

Failure:
StaticPagesControllerTest#test_should_get_about [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:27]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.


rails test test/controllers/static_pages_controller_test.rb:22

F

Failure:
StaticPagesControllerTest#test_should_get_help [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:19]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.


rails test test/controllers/static_pages_controller_test.rb:16

F

Failure:
StaticPagesControllerTest#test_should_get_home [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:12]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.


rails test test/controllers/static_pages_controller_test.rb:4



Finished in 0.252885s, 11.8631 runs/s, 23.7262 assertions/s.
3 runs, 6 assertions, 3 failures, 0 errors, 0 skips
```
ウインドウタイトルの名前が対応していないらしい。

テストのasssert_...が増えていくと、テスト結果のassertionsの数が増えていく。

homeページ

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Home | Ruby on Rails Tutorial Sample App</title>
    <!--上がタイトル-->
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </p>
  </body>
</html>
```
試しにテスト

```
ubuntu:~/environment/sample_app (static-pages) $ rails tRunning via Spring preloader in process 22996
Run options: --seed 46488

# Running:

F

Failure:
StaticPagesControllerTest#test_should_get_about [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:27]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.


rails test test/controllers/static_pages_controller_test.rb:22

F

Failure:
StaticPagesControllerTest#test_should_get_help [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:19]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.


rails test test/controllers/static_pages_controller_test.rb:16

.

Finished in 0.169155s, 17.7352 runs/s, 35.4704 assertions/s.
3 runs, 6 assertions, 2 failures, 0 errors, 0 skips
```
failuresの数が減った。
エラーメッセージもhomeの部分が消えた。
homeのウィンドウタイトルが対応したらしい。

プレビューでもウィンドウタイトル```Home | Ruby on Rails Tutorial Sample App```を確認。
help,aboutもhtmlを変更する。

テストで確認

```
ubuntu:~/environment/sample_app (static-pages) $ rails t
Running via Spring preloader in process 24169
Run options: --seed 18201

# Running:

...

Finished in 0.084690s, 35.4233 runs/s, 70.8467 assertions/s.
3 runs, 6 assertions, 0 failures, 0 errors, 0 skips
```
成功。

####演習

```rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  
  def setup
  # メソッド名
    @base_title = "Ruby on Rails Tutorial Sample App"
    # インスタンス変数
  end
  
  test "should get home" do
    get static_pages_home_url
    # getはGETリクエストで受け付ける普通のWebページを示す
    # GETを受け付けるよね？
    assert_response :success
    # response:successはリクエストが成功し、レスポンスとともに要求に応じた情報が返される
    # GETリクエストが成功、ページが表示されたらいい。
    # response:successは、実際にはHTTPのステータスコード200 OKを指す
  　　　　assert_select "title", "Home | #{@base_title}"
    # assert_selectメソッドは、特定のHTMLタグが存在する確認
    # @base_titleに代入する
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | #{@base_title}"
  end
  
  test "should get about" do
    get static_pages_about_url
    # aboutページを表示させる（GETリクエスト）
    assert_response :success
    # GETリクエストが成功したかを確認
    assert_select "title", "About | #{@base_title}"
  end

end

```
setupメソッドで繰り返し文を入力しなくていい

###レイアウトと埋め込みRuby（Refactor）
Railsのコントローラとアクションを使って3つの有効なページを生成することでさまざまなことを達成した。
しかしまだコードに無駄が多いらしい。
・ページのタイトルがどれもほぼ同じ
・「Ruby on Rails Tutorial Sample App」という文字が3つのタイトルで繰り返しの使用
・HTMLの構造全体が各ページで重複

Rubyの「DRY」（Don’t Repeat Yourself: 繰り返すべからず）という原則がある。これを実行する。
現在は「ほぼ」同じになっているページのタイトルを「完全に」同じにする。この方が、コードの重複を一括で取り除けるから。
重複を取り除くテクニックの１つとして、ビューで「埋め込みRuby」が使えます。
Railsのprovideメソッドを使ってタイトルをページごとに変更

ERB(erb)はWebページに動的な要素を加えるときに使うテンプレートシステム

homeのページ

```html
<% provide(:title, "Home") %>
<!--<% .. %>でprovideメソッドを呼び出す-->
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  　<!--<%= ... %>というよく似た記法を使い、yieldメソッドを呼び出す-->
  　<!--等号を追加すると、テンプレートのその部分に挿入されます-->
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </p>
  </body>
</html>
```
helpページ

```html
<% provide(:title, "Help") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    <h1>Help</h1>
    <p>
      Get help on the Ruby on Rails Tutorial at the
      <a href="https://railstutorial.jp/help">Rails Tutorial help
      section</a>.
      To get help on this sample app, see the
      <a href="https://railstutorial.jp/#ebook">
      <em>Ruby on Rails Tutorial</em> book</a>.
    </p>
  </body>
</html>
```

aboutページ

```html
<% provide(:title, "About") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    <h1>About</h1>
    <p>
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      is a <a href="https://railstutorial.jp/#ebook">book</a> and
      <a href="https://railstutorial.jp/screencast">screencast</a>
      to teach web development with
      <a href="https://rubyonrails.org/">Ruby on Rails</a>.
      This is the sample application for the tutorial.
    </p>
  </body>
</html>
```
home,help,aboutページのコードを整えた部分

```html
<% provide(:title, "The Title") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    Contents
  </body>
</html>
```
整えたのでコードの重複が起きたので、これから埋め込みルビーが出てきそうだ。

各ページの内容をレイアウトに挿入するためのもの

```html
<!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>
```
このコードの詳細な動作を正確に理解することは重要ではない。
レイアウトを使う際に、/static_pages/homeにアクセスするとhome.html.erbの内容がHTMLに変換される。
<% provide(:title, "The Title") %>と<%= yield %>の関係で成り立つコードなのだろう。

そしてこれによりhome,help,aboutページのHTMLが簡素化される

```html
<% provide(:title, "Home") %>
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
  sample application.
</p>
```
helpページ

```html
<% provide(:title, "Help") %>
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="https://railstutorial.jp/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="https://railstutorial.jp/#ebook"><em>Ruby on Rails Tutorial</em>
  book</a>.
</p>
```

aboutページ

```html
<% provide(:title, "About") %>
<h1>About</h1>
<p>
  <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
  is a <a href="https://railstutorial.jp/#ebook">book</a> and
  <a href="https://railstutorial.jp/screencast">screencast</a>
  to teach web development with
  <a href="https://rubyonrails.org/">Ruby on Rails</a>.
  This is the sample application for the tutorial.
</p>
```
一応テスト

```
ubuntu:~/environment/sample_app (static-pages) $ rails t
Running via Spring preloader in process 8600
Run options: --seed 12938

# Running:

...

Finished in 1.339239s, 2.2401 runs/s, 4.4802 assertions/s.
3 runs, 6 assertions, 0 failures, 0 errors, 0 skips
```
成功。

###演習
内容はcontactページが表示され、ウィンドウタイトルがContact | Ruby on Rails Tutorial Sample Appであるかのテスト書けと書いてあった。

```rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  
  def setup
  # メソッド名
    @base_title = "Ruby on Rails Tutorial Sample App"
    # インスタンス変数
  end
  
  test "should get home" do
    get static_pages_home_url
    # getはGETリクエストで受け付ける普通のWebページを示す
    # GETを受け付けるよね？
    assert_response :success
    # response:successはリクエストが成功し、レスポンスとともに要求に応じた情報が返される
    # GETリクエストが成功、ページが表示されたらいい。
    # response:successは、実際にはHTTPのステータスコード200 OKを指す
    assert_select "title", "Home | #{@base_title}"
    # assert_selectメソッドは、特定のHTMLタグが存在する確認
    # @base_titleに代入する
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | #{@base_title}"
  end
  
  test "should get about" do
    get static_pages_about_url
    # aboutページを表示させる（GETリクエスト）
    assert_response :success
    # GETリクエストが成功したかを確認
    assert_select "title", "About | #{@base_title}"
  end
  test "should get contact" do
　  get static_pages_contact_url
　  assert_response :success
　  assert_select "title", "Contact | #{@base_title}"
  end
end
```
テスト

```
ubuntu:~/environment/sample_app (static-pages) $ rails t
Running via Spring preloader in process 10323
Run options: --seed 19623

# Running:

...E

Error:
StaticPagesControllerTest#test_should_get_contact:
NameError: undefined local variable or method `static_pages_contact_url' for #<StaticPagesControllerTest:0x000056032e9439a0>
    test/controllers/static_pages_controller_test.rb:38:in `block in <class:StaticPagesControllerTest>'


rails test test/controllers/static_pages_controller_test.rb:37



Finished in 1.840928s, 2.1728 runs/s, 3.2592 assertions/s.
4 runs, 6 assertions, 0 failures, 1 errors, 0 skips
```
static_pages_contact_urlが見つからないらしい。
コントローラ、アクションを書く。contactページを作る。

```rb
Rails.application.routes.draw do
  get 'static_pages/home'
  # static_pagesコントローラからhomeアクションに紐付けされる
  # getでアクセルすることでページを取得することができる
  get 'static_pages/help'
  # 何を書いているかはわからない
  get 'static_pages/about'
  # aboutアクションにGETリクエストを送る
  get 'static_pages/contact'
  root 'application#hello'
  # rootは流れだったような気がする
  # applicationコントローラのhelloアクションを起こす
end
```
```rb
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
  
  def about
  # aboutアクションを作成
  end
  
  def contact
  end
end
```
```html
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<p>
  Contact the Ruby on Rails Tutorial about the sample app at the
  <a href="https://railstutorial.jp/contact">contact page</a>.
</p>
```
テストを行い成功。
プレビューでも成功を確認