前回は、MVCの全体像を、引きのショットでざっくり眺めてみた。
今回はMVCの肝となるコントローラを作成する手順を学ぶ。
あと、コントローラに対するテストも書いてみる。
【1】準備
いままで何度かやった手順なのでざっと〜。
① アプリケーションの作成
cd /docker-host/share/webapps/
rails _5.1.1_ new sample_app
② Gemを追加
# Gemfileを開く
cd /docker-host/share/webapps/sample_app
vi Gemfile
# 以下を追記
group :test do
gem 'rails-controller-testing'
gem 'minitest-reporters'
gem 'guard'
gem 'guard-minitest'
end
# あとgem取得先のURLをhttpに変更
source 'https://rubygems.org'
↓
source 'http://rubygems.org'
# んでインストール
bundle install --path vendor/bundle
③ gitにコミット
git add .
git commit -m "sample_app作成"
④ とりあえず動作確認
# Puma起動。「rails s」は「rails server」の短縮形
$ rails s
=> Booting Puma
〜 中略 〜
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
# んで、ブラウザから以下でアクセスできればOK
http://localhost:3000/
# 確認できたら、Pumaはいったん停止する( Ctrl-C )
【2】コントローラを生成する
「rails generate 〜」で、コントローラを生成してみる。
① コントローラの生成
cd /docker-host/share/webapps/sample_app
# 「StaticPages」コントローラを作って "home" と "help" というアクションを定義
rails generate controller StaticPages home help
# 何がつくられたか
$ git status -s
M config/routes.rb
?? app/assets/javascripts/static_pages.coffee
?? app/assets/stylesheets/static_pages.scss
?? app/controllers/static_pages_controller.rb
?? app/helpers/static_pages_helper.rb
?? app/views/static_pages/
?? test/controllers/static_pages_controller_test.rb
# views/* の下には何がつくられたか
$ ls -1 app/views/static_pages/
help.html.erb
home.html.erb
# gitにコミット
git add .
git commit -m "StaticPagesコントローラを生成"
生成されるファイルは、前回のscaffoldの生成物から、モデルやDB関連を除いたもの、となっているようだ。
・コントローラ
・ビュー
・ヘルパー
・JSやCSSなどのassets関連
・テスト関連
また、scaffold のときと同様に、ルーティング設定ファイル「 config/routes.rb 」も編集されている。
② 表示確認
# Puma起動
$ rails s
=> Booting Puma
〜 中略 〜
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
# んで、ブラウザから以下のURLにアクセスできればOK
http://localhost:3000/static_pages/home
http://localhost:3000/static_pages/help
# 確認できたら、Pumaはいったん停止する( Ctrl-C )
[補足] generate したけど取り消したい
rails generate controller StaticPages home help
↓に対して...
rails destroy controller StaticPages home help
rails generate model User name:string email:string
↓に対して...
rails destroy model User
など。
【3】ルーティングの設定を確認する
「 config/routes.rb 」
Rails.application.routes.draw do
get 'static_pages/home'
get 'static_pages/help'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
上記は、getメソッドで static_pages/xxx というURLにアクセスすると、StaticPages コントローラのxxxアクションを実行するよ〜、という設定。
【4】コントローラのソースを確認する
「app/controllers/static_pages_controller.rb」
class StaticPagesController < ApplicationController
def home
end
def help
end
end
「rails generate 〜」で指定したアクションのメソッドが定義されている。
命名規則で紐付いたビューを表示するだけなので、処理は何も記述されていない。
【5】ビューのソースを確認する
「app/views/static_pages/home.html.erb」
「app/views/static_pages/help.html.erb」
<h1>StaticPages#home</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>
今回は特になにも書いてないな...
「 app/views/コントローラ名のスネークケース/アクション名.html.erb 」
という命名規則に従うことで、コントローラのアクションと紐付いているというところがポイントかな。
【6】コントローラのテストを書いてみる
scaffold や generate の結果確認で見たように、Rails ではデフォルトのソース群に既にテスト用のリソースが含まれている。
なので、面倒な導入なしにいきなりテストを書ける。
[準備] テストの出力をかっこよくする(任意)
さきの手順でプロジェクトに追加済みの minitest reporters というGemを有効にすると、テストの結果出力が綺麗になってちょっとテンション上がる。
以下のファイルにGemを利用するように記述する。
「test/test_helper.rb」
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
# ↓この2行を追加
require "minitest/reporters"
Minitest::Reporters.use!
class ActiveSupport::TestCase
〜 中略 〜
end
① どんなテストが生成されているのか確認する
コントローラとセットで生成されたテストコードの、デフォルトの状態は以下。
「test/controllers/static_pages_controller_test.rb」
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
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
end
各アクションに対してテストが定義されていて、そのアクションのURLに対してGETでアクセスし、結果が :success(HTTPレスポンス200)かどうかをテストしている。
文法的には、test メソッドに 引数 と ブロックを渡しているのかな。
この段階でいっかいテストを実行してみると、以下のように何事もなく成功する。
※Pumaの起動は必要ない。かわりに Spring というサーバーを起動して実行するので、少し時間がかかる。
$ rails test
Running via Spring preloader in process 517
〜 中略 〜
Started with run options --seed 15128
2/2: [=============================] 100% Time: 00:00:14, Time: 00:00:14
Finished in 14.31579s
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
② これからコントローラに実装する機能に対するテストを先に書いて失敗させてみる
いわゆるテストファーストというやつ。
ここでは、新規に about というアクションを追加する想定で、先にテストコードを書いてみる。
「test/controllers/static_pages_controller_test.rb」
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
〜 中略 〜
# about アクションへのGETが成功するか
test "should get about" do
get static_pages_about_url
assert_response :success
end
end
んで、テストを実行して、失敗することを確認しておく。
$ rails test
Running via Spring preloader in process 611
〜 中略 〜
ERROR["test_should_get_about", StaticPagesControllerTest, 14.417123627001274]
〜 中略 〜
NameError: NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x0055be52dfee48>
test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'
〜 中略 〜
3 tests, 2 assertions, 0 failures, 1 errors, 0 skips
③ about アクションを追加する
③-a コントローラにアクションを追加
「app/controllers/static_pages_controller.rb」
# これを追加
def about
end
③-b ルーティング設定を追加
「config/routes.rb」
# これを追加
get 'static_pages/about'
③-c ビューを新規作成
「app/views/static_pages/about.html.erb」
<% # とりあえずこんな内容で作成 %>
<h1>StaticPages#about</h1>
<p>This is `about` page!</p>
④ んで、再度テストしてみる
$ rails test
〜 中略 〜
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
通った!
今回はなんか簡単でしたが、ひとまず コントローラの作成とテストについて学ぶことができた。
コントローラの詳細については回を追って順次学んでいく想定。
今日はここまで!