v-crn Code Log

主に備忘録

Rails Tutorial 第4版 第3章 演習 解答例

f:id:v-crn:20190711155257p:plain

この文書はRails Tutorial 第4版 第3章 ほぼ静的なページの作成の演習に対する個人の解答例です。解答には誤りや不適切な表現が含まれていることがありますが、もし誤謬を見つけたらコメント頂けると嬉しいです。
それでは、やっていきましょう!

3.1 セットアップ

1. BitbucketがMarkdown記法のREADME (リスト 3.3) をHTMLとして正しく描画しているか、確認してみてください。

READMEが正しく表示されていることを確認しました。なお、今回はGitホスティングサービスとしてBitbucketではなくGithubを使用しています。

https://github.com/v-crn/sample_app

2. 本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。

デプロイの成功を確かめました。

3.2 静的ページ

3.2.1 静的なページの生成

1. Fooというコントローラを生成し、その中にbarとbazアクションを追加してみてください。

$ rails g controller Foo bar baz
Running via Spring preloader in process 70807
      create  app/controllers/foo_controller.rb
       route  get 'foo/bar'
get 'foo/baz'
      invoke  erb
      create    app/views/foo
      create    app/views/foo/bar.html.erb
      create    app/views/foo/baz.html.erb
      invoke  test_unit
      create    test/controllers/foo_controller_test.rb
      invoke  helper
      create    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/foo.coffee
      invoke    scss
      create      app/assets/stylesheets/foo.scss

app/controllers/foo_controller.rb

class FooController < ApplicationController
  def bar
  end

  def baz
  end
end

2. コラム 3.1で紹介したテクニックを駆使して、Fooコントローラとそれに関連するアクションを削除してみてください。

$ rails d controller Foo bar baz
Running via Spring preloader in process 70887
      remove  app/controllers/foo_controller.rb
       route  get 'foo/bar'
get 'foo/baz'
      invoke  erb
      remove    app/views/foo
      remove    app/views/foo/bar.html.erb
      remove    app/views/foo/baz.html.erb
      invoke  test_unit
      remove    test/controllers/foo_controller_test.rb
      invoke  helper
      remove    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/foo.coffee
      invoke    scss
      remove      app/assets/stylesheets/foo.scss

ちなみにアクション名を付けずにrails d controller Fooを実行するとroutes.rbにfooとbarについての記載が残ったままとなります。

3.2.2 静的なページの調整

演習なし。

3.3 テストから始める

3.3.1 最初のテスト

演習なし。

3.3.2 Red

演習なし。

3.3.3 Green

演習なし。

3.3.4 Refactor

演習なし。

3.4 少しだけ動的なページ

3.4.1 タイトルをテストする (Red)

1. StaticPagesコントローラのテスト (リスト 3.24) には、いくつか繰り返しがあったことにお気づきでしょうか? 特に「Ruby on Rails Tutorial Sample App」という基本タイトルは、各テストで毎回同じ内容を書いてしまっています。そこで、setupという特別なメソッド (各テストが実行される直前で実行されるメソッド) を使って、この問題を解決したいと思います。まずは、リスト 3.30のテストが green になることを確認してみてください (リスト 3.30では、2.2.2で少し触れたインスタンス変数や文字列の式展開というテクニックを使っています。それぞれ4.4.5と4.2.2で詳しく解説するので、今はわからなくても問題ありません)。

$ rails test
...

# Running:

...

Finished in 0.571216s, 5.2520 runs/s, 10.5039 assertions/s.

3 runs, 6 assertions, 0 failures, 0 errors, 0 skips

リスト 3.30のテストがgreenになることを確認しました。

3.4.3 レイアウトと埋め込みRuby (Refactor)

サンプルアプリケーションにContact (問い合わせ先) ページを作成してください (ヒント: まずはリスト 3.15を参考にして、/static_pages/contactというURLのページに「Contact | Ruby on Rails Tutorial Sample App」というタイトルが存在するかどうかを確認するテストを最初に作成しましょう。次に、3.3.3でAboutページを作ったときのと同じように、Contactページにもリスト 3.40のコンテンツを表示してみましょう。)。

リスト 3.40: Contactページで使うコード
app/views/static_pages/contact.html.erb

<% 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>

static_pages_controller_test.rbに次のテストを追加。

test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | #{@base_title}"
end

static_pages_controller.rbにcontactメソッドを追加。

class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
    
  def about
  end
    
  def contact
  end
end

routes.rbにcontactアクションを追加。

Rails.application.routes.draw do
  get 'static_pages/home'
  get 'static_pages/help'
  get 'static_pages/about'
  get 'static_pages/contact'
end

テストを実行します。

$ rails t
Running via Spring preloader in process 62815
...
# Running:

....

Finished in 0.442541s, 9.0387 runs/s, 18.0774 assertions/s.

4 runs, 8 assertions, 0 failures, 0 errors, 0 skips

greenになることが確認できました。

3.4.4 ルーティングの設定

1. リスト 3.41にrootルーティングを追加したことで、root_urlというRailsヘルパーが使えるようになりました (以前、static_pages_home_urlが使えるようになったときと同じです)。リスト 3.42のFILL_INと記された部分を置き換えて、rootルーティングのテストを書いてみてください。

test/controllers/static_pages_controller_test.rb

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  test "should get root" do
    get root_url
    assert_response :success
  end

  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

  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end
end

2. 実はリスト 3.41のコードを書いていたので、先ほどの課題のテストは既に green になっているはずです。このような場合、テストを変更する前から成功していたのか、変更した後に成功するようになったのか、判断が難しいです。リスト 3.41のコードがテスト結果に影響を与えていることを確認するため、リスト 3.43のようにrootルーティングをコメントアウトして見て、 red になるかどうか確かめてみましょう (なおRubyのコメント機能については4.2.1で説明します)。最後に、コメントアウトした箇所を元に戻し (すなわちリスト 3.41に戻し)、テストが green になることを確認してみましょう。

$ rails t
Running via Spring preloader in process 66920
...

# Running:

...E

Finished in 0.424922s, 9.4135 runs/s, 7.0601 assertions/s.

  1) Error:
StaticPagesControllerTest#test_should_get_root:
NameError: undefined local variable or method `root_url' for #<StaticPagesControllerTest:0x00007f95a2515448>
    test/controllers/static_pages_controller_test.rb:6:in `block in <class:StaticPagesControllerTest>'

4 runs, 3 assertions, 0 failures, 1 errors, 0 skips

redになることが確認できました。続いてコメントアウトをもとに戻して再度テストします。

$ rails t
Running via Spring preloader in process 67029
...

# Running:

....

Finished in 0.417366s, 9.5839 runs/s, 9.5839 assertions/s.

4 runs, 4 assertions, 0 failures, 0 errors, 0 skips

greenになることが確認できました。

3.5 最後に

3.5.1 本章のまとめ

演習なし。

3.6 高度なセットアップ

3.6.1 minitest reporters

演習なし。

3.6.2 Guardによるテストの自動化

演習なし。