Rails-tutorial自分用まとめ(第3章 主に演習)

その2から続く

3章ほぼ静的なページの作成

3.1 セットアップ

サンプルアプリケーションを作る

cd ~/environment
rails _5.1.6_ new sample_app
cd sample_app/
#Gemfileを編集する。
source 'https://rubygems.org'

gem 'rails',        '5.1.6'
gem 'puma',         '3.9.1'
gem 'sass-rails',   '5.0.6'
gem 'uglifier',     '3.2.0'
gem 'coffee-rails', '4.2.2'
gem 'jquery-rails', '4.3.1'
gem 'turbolinks',   '5.0.1'
gem 'jbuilder',     '2.7.0'

group :development, :test do
  gem 'sqlite3', '1.3.13'
  gem 'byebug',  '9.0.6', platform: :mri
end

group :development do
  gem 'web-console',           '3.5.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.0.2'
  gem 'spring-watcher-listen', '2.0.1'
end

group :test do
  gem 'rails-controller-testing', '1.0.2'
  gem 'minitest',                 '5.10.3'
  gem 'minitest-reporters',       '1.1.14'
  gem 'guard',                    '2.16.2'
  gem 'guard-minitest',           '2.4.4'
end

group :production do
  gem 'pg', '0.20.0'
end
bundle install --without production
bundle update
helloアクションをApplicationコントローラーに追加するapp/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    render html: "hello, world!"
  end
end

ルートルーティングを設定するconfig/routes.rb
Rails.application.routes.draw do
  root 'application#hello'
end

3.2静的なページ

git checkout -b static-pages
#StaticPagesコントローラを生成する
rails generate controller StaticPages home help

コントローラ名をキャメルケース (単語の頭文字を大文字にしてつなぎ合わせた名前) で渡していることに注目。こうすると、StaticPagesコントローラ名をスネークケース
(単語間にアンダースコアを加えて繋ぎ合わせた名前) にした
ファイルstatic_pages_controller.rbを自動的に生成するよ

短縮したコマンド一覧

#完全なコマンド  #短縮形
rails server   #rails s
rails console  #rails c
rails generate #rails g
rails test     #rails t
bundle install #bundle
StaticPagesコントローラ内のhomeアクションとhelpアクションで使うルーティングconfig/routes.rb
Rails.application.routes.draw do
  get  'static_pages/home'
  get  'static_pages/help'
  root 'application#hello'
end
生成されるStaticPagesコントローラapp/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
end
Homeページ用に生成されたビューapp/views/static_pages/home.html.erb
<h1>StaticPages#home</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>

helpアクションに対応するビューも、上のコードと似ている。

Helpページ用に生成されたビューapp/views/static_pages/help.html.erb
<h1>StaticPages#help</h1>
<p>Find me in app/views/static_pages/help.html.erb</p>

演習

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

rails g controller Foo bar baz

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

rails destroy controller Foo bar baz

コントローラーの生成

自動生成と、それに対応する取り消し処理の例

rails generate controller StaticPages home help
rails destroy controller StaticPages home help

モデルの自動生成についても、同様の方法で元に戻せるよ!

rails generate model User name:string email:string
rails destroy model User

元に戻したいときは、db:rollbackで1つ前の状態に戻します。

rails db:migrate
rails db:rollback

最初の状態に戻したいときは、VERSION=0オプションを使います。

rails db:migrate VERSION=0

0を別の数字に置き換えることによって、
指定したバージョンの状態に戻すことができます。

GETやその他のHTTPメソッドについて

クライアント (例えばFirefoxやSafariなどのWebブラウザ)とサーバー (ApacheやNginxなどのWebサーバー)は4つの基本操作(GETPOSTPATCHDELETE)を互いに認識できるようになっています。

GETは最も頻繁に使われるHTTPリクエストで、ページを取得する
主にWeb上のデータを読み取る (get) ときに使われます。

POSTは、GETの次によく使用されるリクエストで、
ページ上のフォームに入力した値を、ブラウザから送信する時に使われます。

例えばRailsアプリケーションでは、POSTリクエストは何かを作成するときによく使われます(なお本来のHTTPでは、POSTを更新に使ってもよいとしている)。
例えばユーザー登録フォームで新しいユーザーを作成するときは、
POSTリクエストを送信します。

PATCHと DELETEという2つの操作があり、それぞれサーバー上の
何かを更新したり削除したりするときに使われます。

RESTとは、アプリケーションを構成するコンポーネント(Userなど)を、RDBMS(リレーショナルデータベースマネジメントシステム)のCRUD(Create/Read/Update/Delete)
・HTTPRequestの各メソッド(GET/POST/PUT/DELETE)
に対応させて、自由に作成/読み出し/更新/削除できるもの

HTTP    Request URL              アクション 用途
GET    /users index       すべてのユーザーを表示するページ
GET    /users/1 show      id=1のユーザーを表示するページ
GET    /users/new new     ユーザーを新規作成するページ
POST   /users create      ユーザーを作成するアクション
GET    /users/1/edit     edit id=1のユーザーを編集するページ
PATCH  /users/1 update   id=1のユーザーを更新するアクション
DELETE /users/1 destroy  id=1のユーザーを削除するアクション
              (リソース)として扱うアーキテクチャ。
HomeページのHTMLを修正するapp/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
  sample application.
</p>
HelpページのHTMLを修正するapp/views/static_pages/help.html.erb
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="https://railstutorial.jp/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="https://railstutorial.jp/#ebook"><em>Ruby on Rails Tutorial</em>
  book</a>.
</p>
生成されるStaticPagesコントローラapp/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
end

StaticPagesControllerというクラスを定義していることが分かります。このようなクラスは、メソッド (関数とも呼ばれます) をまとめるときに便利な手法です。

/static_pages/homeというURLにアクセスすると、
RailsはStaticPagesコントローラを参照し、
homeアクションに記述されているコードを実行します。
その後、そのアクションに対応するビュー (MVCのVに相当) を出力します。

今回の場合、homeアクションが空になっているので、/static_pages/homeにアクセスしても単に対応するビューが出力されるだけです。

プレースホルダ:place holderとは

正式な値が入るまで一時的に場所を確保しておく措置のことです。

3.3 テストから始める

テストスイートとは?

ソフトウェアプログラムが特定の動作を持っていることを示すために
ソフトウェアプログラムをテストするために使用することを目的とした
テストケースの集まりです。

テストケース:test caseとは?

どんな条件の元でどんなテストをするか洗い出してまとめたもの。

テストが揃っていれば、機能停止に陥るような回帰バグ
(Regression Bug: 以前のバグが再発したり機能の追加/
変更に副作用が生じたりすること) を防止できる。

テストが揃っていれば、コードを安全にリファクタリング
(機能を変更せずにコードを改善すること) ができる。

テストコードは、アプリケーションコードから見ればクライアントとして
動作するので、アプリケーションの設計やシステムの他の部分との
インターフェイスを決めるときにも役に立つ。

動的なページを作ろう!

ページ URL 基本タイトル 追加タイトル
Home /static_pages/home “Ruby on Rails Tutorial Sample App” “Home”
Help /static_pages/help “Ruby on Rails Tutorial Sample App” “Help”
About /static_pages/about “Ruby on Rails Tutorial Sample App” “About”

assert_selectメソッドでは、
特定のHTMLタグが存在するかどうかをテストします。

assert_select "title", "Home | Ruby on Rails Tutorial Sample App"

演習

1.Ruby on Rails Tutorial Sample Appという基本タイトルは、各テストで毎回同じ内容を書いてしまっています。そこで、setupという特別なメソッド (各テストが実行される直前で実行されるメソッド)を使おう

基本タイトルを使ったStaticPagesコントローラのテスト green
test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  def setup
    @base_title = "Ruby on Rails Tutorial Sample App"
  end

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | #{@base_title}"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | #{@base_title}"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | #{@base_title}"
  end
end

タイトルにERBを使ったHomeページのビュー green

app/views/static_pages/home.html.erb
<% provide(:title, "Home") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </p>
  </body>

タイトルにERBを使ったHelpページのビューgreen

app/views/static_pages/help.html.erb
<% provide(:title, "Help") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    <h1>Help</h1>
    <p>  Get help on the Ruby on Rails Tutorial at the
      <a href="https://railstutorial.jp/help">Rails Tutorial help
      section</a>.
      To get help on this sample app, see the
      <a href="https://railstutorial.jp/#ebook">
      <em>Ruby on Rails Tutorial</em> book</a>.
    </p>
  </body>

タイトルにERBを使ったAboutページのビュー green

app/views/static_pages/about.html.erb
<% provide(:title, "About") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    <h1>About</h1>
    <p>
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      is a <a href="https://railstutorial.jp/#ebook">book</a> and
      <a href="https://railstutorial.jp/#screencast">screencast</a>
      to teach web development with
      <a href="http://rubyonrails.org/">Ruby on Rails</a>.
      This is the sample application for the tutorial.
    </p>
  </body>
</html>
<% provide(:title, "The Title") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
  <body>
    Contents
  </body>
</html>

テンプレート=Viewを指すよ

provideメソッドはcontent_forの代替

provideメソッドでパラメータを引き渡し
home.html.erb

<% provide(:title, “Home”) %>

yieldメソッドで受け取る
application.html.erb

<title><%= yield(:title) %></title>
<!– <title>Home</title> –>

provideメソッドを呼び出しています。メソッドの引数では、
“Home”という文字列と:titleというラベルを関連付けています

上の部分は重複しているので一つにまとめられる

演習

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

static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
(中略)
  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
  end
end

ルーティング

routes.rb
Rails.application.routes.draw do
(中略)
  get  'static_pages/contact'
end

コントローラーに”contact”アクション追加。

static_pages_controller.rb

class StaticPagesController < ApplicationController
(中略)
  def contact
  end
end

Contactページ編集。

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="http://railstutorial.jp/contact">contact page</a>.
</p>

演習

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

static_pages_controller_test.rb

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  
  def setup
    @base_title="Ruby on Rails Tutorial Sample App"
  end
  
  test "should get root" do
    get root_url
    assert_response :success
  end
(中略)
end

2:rootルーティングをコメントアウトして見て、 red になるかどうか確かめてみましょう。
最後に、コメントアウトした箇所を元に戻しテストが green になることを確認してみましょう。

routes.rb

#コメントアウトする
Rails.application.routes.draw do
  #root  'application#hello'
 end

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

bundle exec guard init
sudo yum install -y tmux  # Cloud9を使っている場合に必要

Guardfile

# Guardのマッチング規則を定義
guard :minitest, spring: "bin/rails test", all_on_start: false do
  watch(%r{^test/(.*)/?(.*)_test\.rb$})
  watch('test/test_helper.rb') { 'test' }
  watch('config/routes.rb')    { integration_tests }
  watch(%r{^app/models/(.*?)\.rb$}) do |matches|
    "test/models/#{matches[1]}_test.rb"
  end
  watch(%r{^app/controllers/(.*?)_controller\.rb$}) do |matches|
    resource_tests(matches[1])
  end
  watch(%r{^app/views/([^/]*?)/.*\.html\.erb$}) do |matches|
    ["test/controllers/#{matches[1]}_controller_test.rb"] +
    integration_tests(matches[1])
  end
  watch(%r{^app/helpers/(.*?)_helper\.rb$}) do |matches|
    integration_tests(matches[1])
  end
  watch('app/views/layouts/application.html.erb') do
    'test/integration/site_layout_test.rb'
  end
  watch('app/helpers/sessions_helper.rb') do
    integration_tests << 'test/helpers/sessions_helper_test.rb'
  end
  watch('app/controllers/sessions_controller.rb') do
    ['test/controllers/sessions_controller_test.rb',
     'test/integration/users_login_test.rb']
  end
  watch('app/controllers/account_activations_controller.rb') do
    'test/integration/users_signup_test.rb'
  end
  watch(%r{app/views/users/*}) do
    resource_tests('users') +
    ['test/integration/microposts_interface_test.rb']
  end
end

# 与えられたリソースに対応する統合テストを返す
def integration_tests(resource = :all)
  if resource == :all
    Dir["test/integration/*"]  else
    Dir["test/integration/#{resource}_*.rb"]
  end
end

# 与えられたリソースに対応するコントローラのテストを返す
def controller_test(resource)
  "test/controllers/#{resource}_controller_test.rb"
end

# 与えられたリソースに対応するすべてのテストを返す
def resource_tests(resource)
  integration_tests(resource) << controller_test(resource)
end
bundle exec guard
git add -A
git commit -m "Complete advanced setup"

3章のまとめ

  1. 新しいRailsアプリケーションを作成したのはこれで3度目。
    今回も必要なgemのインストール、
    リモートリポジトリへのプッュ、production環境まで行った。

  2. コントローラを新規作成するためのrailsコマンドは
    rails g controller ControllerName アクション名 (省略可)。
    新しいルーティングはconfig/routes.rbファイルで定義する
    Railsのビューでは、静的HTMLの他にERB (埋め込みRuby: Embedded RuBy) が使える。

  3. 常に自動化テストを使って新機能開発を進めることで、
    自信を持ってリファクタリングできるようになり、回帰バグも素早くキャッチできるようになる。

  4. テスト駆動開発では「red ・ green ・REFACTOR」サイクルを繰り返す

  5. Railsのレイアウトでは、
    アプリケーションのページの共通部分をテンプレートに
    置くことでコードの重複を解決することができる。

  6. コミット時に「マージするとSpringのプロセスID (pid) ファイルが上書きされる可能性があります」のようなエラーメッセージが表示される場合は、
    コマンドラインでrm -f *.pidを実行してpidファイルを削除。

  7. 今はWebデザインで一般に使われるスタブ用の (とりあえずのダミーとして使われる)URL「’#’」を置いておきます。第3引数はオプションハッシュで、
    この場合はサンプルアプリのリンクでCSS id logoを指定しています

  8. navタグには「その内側がナビゲーションリンクである」という意図を明示的に伝える役割があります。

  9. alt属性は、画像がない場合に代わりに表示される文字列です

その4に続く

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です