Ruby on Rails チュートリアルで30歳までに人生を変える(第3章)
こんちには、opiyoです。
人生の生き残りをかけて始めた「Railsブートキャンプ」ですが、今日はRailsチュートリアル第3章をやっていこうと思います。
railsチュートリアル 3章の流れ
静的なページのセットアップ
繰り返しの復習は大事です。人間はすぐに忘れてしまう動物なので。
改めてrails new
して最低限のところまでを作ります!
https://railstutorial.jp/chapters/static_pages?version=5.0#sec-sample_app_setup
$ rails _5.0.0.1_ new sample_app
- Gemfileをいじります
source 'https://rubygems.org' gem 'rails', '5.0.0.1' gem 'puma', '3.4.0' gem 'sass-rails', '5.0.6' gem 'uglifier', '3.0.0' gem 'coffee-rails', '4.2.1' gem 'jquery-rails', '4.1.1' gem 'turbolinks', '5.0.1' gem 'jbuilder', '2.4.1' group :development, :test do gem 'sqlite3', '1.3.11' gem 'byebug', '9.0.0', platform: :mri end group :development do gem 'web-console', '3.1.1' gem 'listen', '3.0.8' gem 'spring', '1.7.2' gem 'spring-watcher-listen', '2.0.0' end group :test do gem 'rails-controller-testing', '0.1.1' gem 'minitest-reporters', '1.1.9' gem 'guard', '2.13.0' gem 'guard-minitest', '2.4.4' end group :production do gem 'pg', '0.18.4' end # Windows環境ではtzinfo-dataというgemを含める必要があります gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
$ bundle install --without production
- エラーが出たら
$ bundle update
する
- エラーが出たら
git
を使ってsample_app
をバージョン管理下にする- トップページ(hogehoge.com/)に
hello world
を表示されるようにコードを修正する heroku
の設定を行いpush
しますheroku open
してhello world
が表示されればOK
git
とheroku
の設定はチュートリアルを見ずにやってみることで、覚えているかの復習になりますね!
コントローラーの作り方
- 表記はキャメルケース = 単語の先頭を大文字になる(StaticPages)
- アクション名は全て小文字にする
- 出来上がるコントローラーファイル名はスネークケース = 単語をアンダーバー
_
でつなぎ合わせた名前になる
$ rails g controller StaticPages home help # コントローラー名 アクション名ですね create app/controllers/static_pages_controller.rb # 出来上がったコントローラーのファイル route get 'static_pages/help' route get 'static_pages/home' invoke erb create app/views/static_pages create app/views/static_pages/home.html.erb create app/views/static_pages/help.html.erb invoke test_unit create test/controllers/static_pages_controller_test.rb invoke helper create app/helpers/static_pages_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/static_pages.coffee invoke scss create app/assets/stylesheets/static_pages.scss
- routes.rbが自動的に更新される
Rails.application.routes.draw do get 'static_pages/home' # 自動的に追加されたよ get 'static_pages/help' # 自動的に追加されたよ root 'application#hello' end
このgetは、/static_pages/home/
というURLでアクセスされたら、static_pages
コントローラーのhome
アクションと結びつく設定になります。
テスト駆動開発 (TDD)
考え方
テストの手法のひとつで、最初に「正しいコードがないと失敗するテスト」を書き、次に本編のコードを書いてそのテストがパスするようにする考え、やり方かな。
テストをするメリットはチュートリアルのコラムの中で書かれてますが、引用します。
さらに詳細までみたいな場合は、こちらからどうぞ(コラム3-3.です)
https://railstutorial.jp/chapters/static_pages?version=5.0#sec-custom_static_pages
当たり前ですが、何か問題があるとお客様に迷惑をかけます。それは本当に申し訳無いところなのですが、お客様以外のところで凄く面倒なことになります。
だからテストを書くのです。もーこれだけ。
テストコードの書き方
テストコードはrails g controller
を実行した時点で作成されます。
require 'test_helper' class StaticPagesControllerTest < ActionDispatch::IntegrationTest test "should get home" do get static_pages_home_url assert_response :success end end
これを日本語で表すと、「Homeページのテスト。GETリクエストをhomeアクションに対して発行 (=送信) せよ。そうすれば、リクエストに対するレスポンスは[成功]になるはず。」となります。
テストの実行方法は
$ rails test # Running: .. Finished in 1.467940s, 1.3625 runs/s, 1.3625 assertions/s. 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
0 errorsとなっているので、成功(GREEN)したことが分かりますね。
もしエラーになる場合は、こちらに回避方法書いたので参考にしてください。 opiyotan.hatenablog.com
このように、テストと一緒にコードを書いていくことが最近は推奨されています。
3.3.1では、TDDの考えに基づき失敗するエラーを書いて成功させリファクタリングするという流れでテストする方法が乗っていますので是非チャレンジしてみてください。
動的にタイトルを変更する
先ずは各ページのタイトルをチェックするテストを書きます。
もちろん、view
のtitle
タグは何も変更していないのでエラー(RED)になります。
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" # ここ追加しました。"title"タグに書かれた文字列をチェックするテストです end end
では、次にview
のtitle
タグを修正していきます。始めにapp/views/static_pages/home.html.erb
ファイルから。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <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="http://railstutorial.jp/">Ruby on Rails Tutorial</a> </p> </body> </html>
この状態でテストを実行するとhome
アクションについては修正したのでエラーじゃなくなりますが他の2つのアクションがエラーになります
$ rails test # Running: Failure: StaticPagesControllerTest#test_should_get_about [/Users/taku/rails/railstutorial/sample_app/test/controllers/static_pages_controller_test.rb:19]: <About | Ruby on Rails Tutorial Sample App> expected but was <SampleApp>.. Expected 0 to be >= 1. bin/rails test test/controllers/static_pages_controller_test.rb:16 Failure: StaticPagesControllerTest#test_should_get_help [/Users/taku/rails/railstutorial/sample_app/test/controllers/static_pages_controller_test.rb:13]: <Help | Ruby on Rails Tutorial Sample App> expected but was <SampleApp>.. Expected 0 to be >= 1. bin/rails test test/controllers/static_pages_controller_test.rb:10 Finished in 0.649278s, 4.6205 runs/s, 9.2410 assertions/s. 3 runs, 6 assertions, 2 failures, 0 errors, 0 skips
なので、エラー(RED)にならないようhelp
とabout
も修正し成功(GREEN)させます。
リファクタリング
今までは全てのview
ファイルに直接title
タグを書き込んでいました。なので当然表示されるタイトルも変わってきます。
これらを今テストでやったように共通にできるところは共通化し、違う部分だけを設定するように修正していきます。
このように同じコードを繰り返し書かないようにする考え方を「DRY(Don’t Repeat Yourself: 繰り返すべからず) 」と言います。
では早速やってみます。先ずは各ページに動的に変更する部分を書いていきます。
app/views/static_pages/home.html.erb
<% provide(:title, "Home") %> # 各ビュー毎に文字列をセットする <!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="http://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p> </body> </html>
次に共通のビューになるapplication.html.erb
のtitle
をyield
関数を使って表示されるようにします
<!DOCTYPE html> <html> <head> <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> # ここですねー <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <%= yield %> # ここで各ページを読み込んでいるから、各ビューでは`head`タグとかがいらないんですね </body> </html>
それぞれのページでは違う処理だけ書く。共通部分はapplication.html.erb
で定義する!!
<% provide(:title, "Home") %> <h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p>
railsチュートリアル 3章の演習問題
3.1 演習
問題1
BitbucketがMarkdown記法のREADME (リスト 3.3) をHTMLとして正しく描画しているか、確認してみてください。
回答1
ぼくは、githubで作業しているのですが問題なく描画されていますね。
- h1は大きな文字
- h2は少し大きな文字
- リンクは青色で
- コード部分は灰色になる
https://github.com/nakanoTaku/railstutorial_3
問題2
本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。
回答2
hello worldが表示されているのでOKですね!
heroku logs
でログを見ることも出来ます。
3.2.1 演習
問題1
Fooというコントローラを生成し、その中にbarとbazアクションを追加してみてください。
回答1
$ rails g controller Foo bar baz class FooController < ApplicationController def bar end def baz end end
問題2
コラム 3.1で紹介したテクニックを駆使して、Fooコントローラとそれに関連するアクションを削除してみてください。
回答2
$ rails destroy controller Foo bar baz
3.4.2 演習
テストを一部リファクタリングします。
3つのアクションで同じように使われている文字列「Ruby on Rails Tutorial Sample App」を変数に代入し、使い回すようにします。
require 'test_helper' class StaticPagesControllerTest < ActionDispatch::IntegrationTest def setup @base_title = "Ruby on Rails Tutorial Sample App" # setupというテストが実行される前に処理されるメソッド内で文字列を変数にセットしておきます。 end test "should get home" do get static_pages_home_url assert_response :success assert_select "title", "Home | #{@base_title}" # 変数を参照するように修正します。 end end
3.4.4 演習
問題1
リスト 3.41にrootルーティングを追加したことで、root_urlというRailsヘルパーが使えるようになりました (以前、static_pages_home_urlが使えるようになったときと同じです)。リスト 3.42のFILL_INと記された部分を置き換えて、rootルーティングのテストを書いてみてください。
回答1
test "should get root" do get root_url assert_response :success end
問題2
実はリスト 3.41のコードを書いていたので、先ほどの課題のテストは既に green になっているはずです。このような場合、テストを変更する前から成功していたのか、変更した後に成功するようになったのか、判断が難しいです。リスト 3.41のコードがテスト結果に影響を与えていることを確認するため、リスト 3.43のようにrootルーティングをコメントアウトして見て、 red になるかどうか確かめてみましょう (なおRubyのコメント機能については4.2.1で説明します)。最後に、コメントアウトした箇所を元に戻し (すなわちリスト 3.41に戻し)、テストが green になることを確認してみましょう。
回答2
ちゃんとREDになるし、GREEMにもなる
railsチュートリアル 3章で学んだこと
テストをパワーアップする
minitest reporters
テストの成功(RED)失敗(GREEN)の見栄えをよくしてくれます。
準備するのはこれだけ、是非試してみてください!
# ファイル名:test/test_helper.rb ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' require "minitest/reporters" Minitest::Reporters.use! class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all # Add more helper methods to be used by all tests here... end
Guard
ファイルの変更を検出して必要なテストだけを自動実行してくれるそうです。
例えば、「home.html.erbファイルが変更されたらstatic_pages_controller_test.rbを自動的に実行する」といったことをGuardで設定することができます。
これヤバいですね。今はまだ変更するファイルも少ないですし何をしたか全部記憶できるくらいしかないですが絶対面倒になって忘れますよね。
詳細な設定方法はRailsチュートリアルを参照してください。
https://railstutorial.jp/chapters/static_pages?version=5.0#sec-guard
手順だけ簡単にまとめておきます。
- 初期化
$ bundle exec guard init
初期化を実行すると、「/Guardfile」が作成されます。
- Guardfileを編集する
- .gitignoreにSpringを追加する
- Guardの実行
$ bundle exec guard
なんか実行すると「Ctrl + D」か「テストが成功」するまで終わらないのだけど、これは正しい動きなのか?
ずっとバックグラウンドで動かしておいて、常に監視させておくってことなのかな...
あーすごい便利かなーと思ったけど、これは使わないかもしれない。邪魔っちー
httpメソッド
HTTP (HyperText Transfer Protocol) には4つの基本的な操作があり、それぞれGET、POST、PATCH、DELETEという4つの動詞に対応づけられています。クライアント (例えばFirefoxやSafariなどのWebブラウザ) とサーバー (ApacheやNginxなどのWebサーバー) は、上で述べた4つの基本操作を互いに認識できるようになっています
- get
主にWeb上のデータを読み取る (get) ときに使われるリクエストです。
- post
ページ上のフォームに入力した値を、ブラウザから送信する時に送られるリクエストです。
gitでaddとcommitを一回でやる!
$ git commit -am "Improve the README"
herokuへpushした時に何かエラー
$ heroku logs
新しいブランチの作り方
$ git checkout -b hogehoge
今チェックアウトしているブランチは?
$ git branch master * static-pages
ブランチを指定してpushするには?
$ git push origin hogehoge
rails g をやり直したい!
$ rails destroy controller StaticPages home help $ rails destroy model User
Unixプロセスの確認
$ ps aux $ ps aux | grep spring $ ps aux | grep spring taku 7781 0.0 0.2 2518224 19900 ?? S 5:23PM 0:00.42 spring server | sample_app | started 31 mins ago taku 8561 0.0 0.0 2423376 216 s003 R+ 5:55PM 0:00.00 grep spring taku 7782 0.0 0.9 2577420 73224 ?? Ss 5:23PM 0:02.75 spring app | sample_app | started 31 mins ago | test mode $ spring stop $ ps aux | grep spring taku 8604 0.0 0.0 2434840 804 s003 S+ 5:57PM 0:00.00 grep spring # 「7781」「7782」が無くなった!
railsチュートリアル 3章のまとめ
3章ではテスト駆動開発 (TDD)に沿って、開発を進めてきました。 簡単にまとめるこんな感じでしょうか?
- 何事も繰り返し行うことで覚えることができる
rails new
git init
~git push
までの流れ
rails g controller ControllerName アクション名
でコントローラーが作れる- RailsのビューはRubyのコードが使える
- テスト駆動開発 (TDD)は、「RED」「GREEN」「REFACTOR」のサイクルを繰り返して開発をすることだ
では、最後にぼくが一番尊敬している先輩エンジニアからの名言でお別れしましょー
テストコードが仕様書だ