kuma0319のブログ

webエンジニアになるためのアウトプットブログ

Ruby on Railsチュートリアル第5章

Railsチュートリアルの第5章を進めていきます。

第5章(レイアウトを作成する)

Bootstrapやcss関連のところは、飛ばしながらコピペでいきます。

ナビゲーション

  • link_toメソッドはHTMLのaタグを生成する。
  • 第1引数としてリンクテキスト、第2引数としてURL(名前付きルーティング)を取る。
  • <li><%= link_to "Home", '#' %></li>は、<li><a href="#">Home</a></li>を返す。
image_tag
  • image_tagヘルパーは、シンボルを使用してalt属性やwidth属性を設定可能。
  • ソースには、完全なパス、もしくはapp/assets/imagesディレクトリ配下のファイルを指定可能。

例えば、以下のように記述されたERBは

<%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200"),
                      "https://rubyonrails.org/" %>

以下のHTMLが返される。

<img alt="Rails logo" width="200px" src="/assets/rails-<long string>.svg">

パーシャル

  • ビューの重複する記述に関してはパーシャルにまとめる。
  • パーシャルはディレクトリ内で一目見ただけでわかるように、ファイル名の先頭にアンダースコア「_」を付す。
  • パーシャルの呼出しには<%= render 'layouts/header' %>のような形でrenderヘルパーで呼び出す。この際に探すファイル名はapp/views/layouts/_header.html.erbとなる。

アセットパイプライン

アセットパイプラインはJavaScriptCSSの連結圧縮するフレームワークで、重要な部分なのでまとめておきます。

レイアウトのリンク

名前付きルーティング

ERBテンプレートに記述するリンクは

<a href="/static_pages/about">About</a>

のように、素のHTMLを記述可能であるがRails流では無い。

URLは/static_pages/aboutよりも/aboutの方がよく、ERBの名前付きルーティングを使用するのが慣習。

<%= link_to "About", about_path %>
ルーティングの記述
  • root_pathはルートURL以下の文字列「'/'」を返す。
  • root_urlは完全なURLの文字列「'https://www.example.com/'」を返す。
  • 基本的にはpath書式を使用し、リダイレクト時のみurl書式を使用するのが慣習。
  • これまでのget "static_pages/help"のような記述は、get "/help", to: "static_pages#help"とする。これによって、/helpページをGETリクエストされた際に、helpアクションを呼び出す。更に名前付きルーティングも使用できるようになる。

統合テスト

統合テストに入ります。ここでは、上記のルーティングのテストをおこないます。
まずは、テストテンプレートを生成。

$ rails generate integration_test site_layout

テストの手順の通りに書いてみる。 1. ルートURL(Homeページ)にGETリクエストを送る。
2. 正しいページテンプレートが描画されているかどうか確かめる。
3. Home、Help、About、Contactの各ページへのリンクが正しく動くか確かめる。

[test/integration/site_layout_test.rb]
require "test_helper"

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path                         #ルートURLへアクセス。
    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
  end
end

ユーザー登録の実装

rails generateでコントローラを作成する。ユーザー登録はRESTに従いnewアクションを指定。

$ rails generate controller Users new

後は、サインアップ用にルーティングの設定、サインアップ用ボタンへのリンク追加、サインアップページを作成したら最初のステップは完了。

開発環境が動かなくなったとき

  1. 以下のコマンドを実行する。
$ bundle exec rails app:update:bin
  1. git statusでファイルに変更が生じているかどうかを確認。
  2. 変更が生じていたら、git commit -am "Update bin files"を実行。
  3. 再度git push

これで復活出来ることがあるらしいです。

第5章ー演習ー

5.1.1

飛ばします。

5.1.2

飛ばします。

5.1.3

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

[app/views/layouts/application.html.erb]
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <%= render 'layouts/rails_default' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
    </div>
  </body>
</html>

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

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

[app/views/layouts/_rails_default.html.erb]
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>

5.2.2

飛ばします。

5.3.2

確認だけなので飛ばします。

5.3.3

確認だけなので飛ばします。

5.3.4

①footerパーシャルのabout_pathをcontact_pathに変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。
(解答) ちゃんとaboutリンクが無いとエラーが出た。

 FAIL SiteLayoutTest#test_ルートURLのリンクテスト (1.78s)
        Expected at least 1 element matching "a[href="/about"]", found 0..
        Expected 0 to be >= 1.
        test/integration/site_layout_test.rb:10:in `block in <class:SiteLayoutTest>'

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

[test/helpers/application_helper_test.rb]
require "test_helper"

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

5.4.1

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

[test/controllers/users_controller_test.rb]
class UsersControllerTest < ActionDispatch::IntegrationTest
  test "should get new" do
    get signup_path
    assert_response :success
  end
end

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

ERROR UsersControllerTest#test_should_get_new (0.15s)
Minitest::UnexpectedError:         NameError: undefined local variable or method `signup_path' for #<UsersControllerTest:0x00007f9df09e5af8>
            test/controllers/users_controller_test.rb:5:in `block in <class:UsersControllerTest>'

5.4.2

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

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

ERROR UsersControllerTest#test_should_get_new (0.13s)
Minitest::UnexpectedError:         NameError: undefined local variable or method `signup_path' for #<UsersControllerTest:0x00007f0062b8b758>
            test/controllers/users_controller_test.rb:5:in `block in <class:UsersControllerTest>'

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

[test/integration/site_layout_test.rb]
  test "signup path layout links" do
    get signup_path                                 #サインアップへアクセス。
    assert_template 'users/new'                     #指定のレイアウトが表示されるか
    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 "title", full_title("Sign up")    #タイトルが正しいか
  end

第5章ーまとめー

  • ビューの重複するファイルはパーシャルにまとめ、パーシャルはパーシャルであると認識出来るようにファイル名にアンダースコアを付ける。
  • アセットパイプラインはJacaScriptやCSSを結合圧縮し、ページの表示速度を向上させる重要な機能。
  • レイアウトのリンクは名前付きルーティングを使えるような形にする。
  • 統合テストでは、複数の機能が連動するような場面で活用する。

第5章終わり🐻