【Railsチュートリアル】第5章 レイアウトを作成する 演習と解答

# 5.1 構造を追加する

## 5.1.1 ナビゲーション

### 演習 1

Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。リスト 5.4のコマンドを使って、図 5.3のネコ画像をダウンロードしてきましょう11 。

ダウンロードできました。

### 演習 2

mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください（参考: 5.2.1）。

```ruby
$ mv kitten.jpg app/assets/images
```

### 演習 3

image_tagを使って、kitten.jpg画像を表示してみてください

```ruby
<%= link_to image_tag("kitten.jpg", alt: "kitten") %>
```

## 5.1.2 BootstrapとカスタムCSS

### 演習 1

リスト 5.10を参考にして、5.1.1.1で使ったネコ画像をコメントアウトしてみてください。また、ブラウザのHTMLインスペクタ機能を使って、コメントアウトするとHTMLのソースからも消えていることを確認してみてください。

```ruby
home.html.erb
<%#= link_to image_tag("kitten.jpg", alt: "kitten", width: "200px") %>
```

デベロッパーツールで確認したらHTMLソースから消えていました。

### 演習 2

リスト 5.11のコードをcustom.scssに追加し、すべての画像を非表示にしてみてください。うまくいけば、Railsのロゴ画像がHomeページから消えるはずです。先ほどと同様にインスペクタ機能を使って、今度はHTMLのソースコードは残ったままで、画像だけが表示されなくなっていることを確認してみてください。

ロゴ画像はページから消えていますが、デベロッパーツールで確認するとコードは残っていました。

## 5.1.3 パーシャル（partial）

### 演習 1

Railsがデフォルトで生成するheadタグの部分を、リスト 5.18のようにrenderに置き換えてみてください。ヒント: 単純に削除してしまうと後でパーシャルを１から書き直す必要が出てくるので、削除する前にどこかに退避しておきましょう。

```ruby
  <head>
    <title><%= full_title(yield(:title)) %></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' %>
    <%= render 'layouts/shim' %>
  </head>

⬇

 <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= render 'layouts/rails_default' %>
    <%= render 'layouts/shim' %>
  </head>
```

### 演習 2

リスト 5.18のようなパーシャルはまだ作っていないので、現時点ではテストは red になっているはずです。実際にテストを実行して確認してみましょう。

```ruby
ERROR["test_should_get_root", #<Minitest::Reporters::Suite:0x0000558b759adfc0 @name="StaticPagesControllerTest">, 8.660289608999847]
 test_should_get_root#StaticPagesControllerTest (8.66s)
ActionView::Template::Error:         ActionView::Template::Error: Missing partial layouts/_rails_default with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in:
          * "/home/ubuntu/environment/sample_app/app/views"
          * "/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actiontext-6.0.3/app/views"
          * "/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionmailbox-6.0.3/app/views"
        
            app/views/layouts/application.html.erb:5
            test/controllers/static_pages_controller_test.rb:11:in `block in <class:StaticPagesControllerTest>'
```

### 演習 3

layoutsディレクトリにheadタグ用のパーシャルを作成し、先ほど退避しておいたコードを書き込み、最後にテストが green に戻ることを確認しましょう。

GREENになりました。

# 5.2 Sassとアセットパイプライン

## 5.2.2 素晴らしい構文を備えたスタイルシート

### 演習 1

5.2.2で提案したように、footerのCSSを手作業で変換してみましょう。具体的には、リスト 5.17の内容を１つずつ変換していき、リスト 5.20のようにしてみてください。

```ruby
@import "bootstrap-sprockets";
@import "bootstrap";

/* mixins, variables, etc. */
$gray-medium-light: #eaeaea;

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
  h1 {
    margin-bottom: 10px;
  }
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: #777;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}

/* header */
#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: #fff;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
  &:hover {
  color: #fff;
  text-decoration: none;
	}
}

img {
  display: none;
}

/* footer */

footer {
  margin-top: 45px;
  padding-top: 5px;
  border-top: 1px solid $gray-medium-light;
  color: #777;
  a {
    color: #555;
    &:hover {
    color: #222;
    }
  }
  small {
    float: left;
  }
  ul {
    float: right;
    list-style: none;
    li {
      float: left;
      margin-left: 15px;
    }
  }
}
```

# 5.3 レイアウトのリンク

## 5.3.2 RailsのルートURL

### 演習 1

実は名前付きルートは、as:オプションを使って変更することができます。有名なFar Sideの漫画に倣って、Helpページの名前付きルートをhelfに変更してみてください（リスト 5.29）。

```ruby
Rails.application.routes.draw do
  root 'static_pages#home'
  get '/help',    to: 'static_pages#help', as: 'helf' # asを追加
  get 'about',    to: 'static_pages#about'
  get '/contact', to: 'static_pages#contact'
end
```

### 演習 2

先ほどの変更により、テストが red になっていることを確認してください。リスト 5.28を参考にルーティングを更新して、テストを green にして見てください。

```ruby
ERROR["test_should_get_help", #<Minitest::Reporters::Suite:0x0000558d4527bdc0 @name="StaticPagesControllerTest">, 1.4004460740000013]
 test_should_get_help#StaticPagesControllerTest (1.40s)
NameError:         NameError: undefined local variable or method `help_path' for #<StaticPagesControllerTest:0x0000558d45277c48>
            test/controllers/static_pages_controller_test.rb:17:in `block in <class:StaticPagesControllerTest>'
```

```ruby
test "should get help" do
    get helf_path
    assert_response :success
    assert_select "title", "#{@base_title}"
  end
```

GREENになりました。

### 演習 3

エディタのUndo機能を使って、今回の演習で行った変更を元に戻して見てください。

`⌘+ Z`で元に戻しました。

## 5.3.3 名前付きルート

### 演習 1

リスト 5.29のようにhelfルーティングを作成し、レイアウトのリンクを更新してみてください。

```ruby
NameError in StaticPages#contact

Showing /home/ubuntu/environment/sample_app/app/views/layouts/_header.html.erb where line #7 raised:

undefined local variable or method `help_path' for #<#<Class:0x00007fa0ae7ed7a8>:0x00007fa0aec5f458>
Did you mean?  helf_path

Extracted source (around line #7):
<ul class="nav navbar-nav navbar-right">
        <li><% link_to "Home", root_path %></li>
        <li><% link_to "Help", help_path %></li>
        <li><% link_to "Log in", '#' %></li>
      </ul>
    </nav>
```

### 演習 2

前回の演習と同様に、エディタのUndo機能を使ってこの演習で行った変更を元に戻してみてください。

戻しました。通常通りサイトは見ることができます。

## 5.3.4 リンクのテスト

### 演習 1

footerパーシャルのabout_pathをcontact_pathに変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。

動作確認のみなので省略。

### 演習 2

リスト 5.35で示すように、Applicationヘルパーで使っているfull_titleヘルパーを、test環境でも使えるようにすると便利です。こうしておくと、リスト 5.36のようなコードを使って、正しいタイトルをテストすることができます。ただし、これは完璧なテストではありません。例えばベースタイトルに「Ruby on Rails Tutoial」といった誤字があったとしても、このテストでは発見することができないでしょう。この問題を解決するためには、full_titleヘルパーに対するテストを書く必要があります。そこで、Applicationヘルパーをテストするファイルを作成し、リスト 5.37のFILL_INの部分を適切なコードに置き換えてみてください。ヒント: リスト 5.37ではassert_equal <期待される値>, <実際の値>といった形で使っていましたが、内部では==演算子で期待される値と実際の値を比較し、正しいかどうかのテストをしています。

```ruby
application_helper.rb
module ApplicationHelper

 # ページごとの完全なタイトルを返します。
  def full_title(page_title = '') 
    base_title = "Ruby on Rails Tutoial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end
```

```ruby
application_helper_test.rb
require 'test_helper'

class ApplicationHelperTest < ActionView::TestCase
  test "full title helper" do
    assert_equal full_title, "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end
end
```

## 5.4 ユーザー登録: 最初のステップ

### 5.4.1 Usersコントローラ

### 演習 1

表 5.1を参考にしながらリスト 5.41を変更し、users_new_urlではなくsignup_pathを使えるようにしてみてください。

```ruby
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest
  test "should get new" do
    get signup_path
    assert_response :success
  end

end
```

### 演習 2

先ほどの変更を加えたことにより、テストが red になったことを確認してください。なお、この演習はテスト駆動開発（コラム 3.3）で説明した red / green のリズムを作ることを目的としています。このテストは次の5.4.2で green になるよう修正します。

```ruby
ERROR["test_should_get_new", #<Minitest::Reporters::Suite:0x00007f95554a6478 @name="UsersControllerTest">, 0.01274084499982564]
 test_should_get_new#UsersControllerTest (0.01s)
NameError:         NameError: undefined local variable or method `signup_path' for #<UsersControllerTest:0x00007f955541cf98>
            test/controllers/users_controller_test.rb:5:in `block in <class:UsersControllerTest>'
```

NameError: undefined local variable or method

変数やメソッドが定義されていないことにより起こるエラー

## 5.4.2 ユーザー登録用URL

### 演習 1

もしまだ5.4.1.1の演習に取り掛かっていなければ、まずはリスト 5.41のように変更し、名前付きルートsignup_pathを使えるようにしてください。また、リスト 5.43で名前付きルートが使えるようになったので、現時点でテストが green になっていることを確認してください。

確認できました。

### 演習 2

先ほどのテストが正しく動いていることを確認するため、signupルートの部分をコメントアウトし、テスト red になることを確認してください。確認できたら、コメントアウトを解除して green の状態に戻してください。

確認できました。

### 演習 3

リスト 5.32の統合テストにsignupページにアクセスするコードを追加してください（getメソッドを使います）。コードを追加したら実際にテストを実行し、結果が正しいことを確認してください。ヒント: リスト 5.36で紹介したfull_titleヘルパーを使ってみてください。

```ruby
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
    assert_select "a[href=?]", signup_path
    get contact_path
    assert_select "title", full_title("Contact")
    get signup_path
    assert_select "title", full_title("Sign up")
  end
end
```

# さいごに
AWSの容量が途中で足らなくなり、environmentを作り直しました。
このエラーのおかげて、GitHubからcloneする方法を学びましたが、それと引き換えにHerokuにでプライができなくなりました。

Herokuがインストールできていない、とわかったのでインストールをしようとしましたが、エラーが出て前にすすみません。

```:terminal
$ source <(curl -sL https://cdn.learnenough.com/heroku_install)
```

```:terminal
┌──────────────────────────────────────────────────────────┐
│                 npm update check failed                  │
│           Try running with sudo or get access            │
│           to the local update config store via           │
│ sudo chown -R $USER:$(id -gn $USER) /home/ubuntu/.config │
└──────────────────────────────────────────────────────────┘

```

```
sudo chown -R $USER:$(id -gn $USER) /home/ubuntu/.config
```
上記のコマンドを試しても、解決できませんでした。
一旦デプロイせずに前に進もうとおもいます！