Ruby on Rails Tutorial 3章 メモ

# 基本用語
## DRY
Don’t Repeat Yourself(繰り返すべからず)
同じコードを繰り返すことはRubyの原則に反する。

# 文法
## rails generate controller
コントローラを生成する。

```
rails generate controller ControllerName action1 action2
```
## touch
ファイルを作成する。

```
 touch app/views/static_pages/about.html.erb
```

## <%= csrf_meta_tags %>
Web攻撃手法の１つであるクロスサイトリクエストフォージェリー (Cross-Site Request Forgery: CSRF)を防ぐ。

```
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    <%= csrf_meta_tags %> <!--Web攻撃手法の１つであるクロスサイトリクエストフォージェリー (Cross-Site Request Forgery: CSRF)を防ぐ-->
  .
  .
  .
</html>
```

# 短縮系
| 完全なコマンド    | 短縮形   | 
|:----------------|:--------|
| rails server    | rails s |
| rails console   | rails c |
| rails generate  | rails g |
| rails test      | rails t |
| bundle install  | bundle  |

# 元に戻す
## rails destroy controller
コントローラーを取り消す。

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

## rails destroy model
モデルを取り消す。

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

## rails db:rollback
マイグレーションの変更を取り消す。
db/schema.rbの内容を調べることで、ロールバックが成功したかどうか確認出来る。
```
rails db:migrate
rails db:rollback # １つ前の状態に戻す
rails db:migrate VERSION=0 # 最初の状態に戻す
# 上記の0を別の数字に置き換えることによって、指定したバージョンの状態に戻すことができる
```

# テスト
## テストの文法
### テストの例
```test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do # Homeページのテスト
    get static_pages_home_url # GETリクエストをhomeアクションに対して発行 (=送信) せよ
    assert_response :success # そうすれば、リクエストに対するレスポンスは[成功]になるはず
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
  end

end
```

### assert_selectメソッド
タグ内に指定の文字列があると主張する。

```
assert_select "tag_name", "message" # <title>タグ内に「message」という文字列があると主張する
```

### set upメソッド
各テストが実行される直前で実行されるメソッド。

```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
end
```

### 埋め込みRuby

```
<% provide(:title, "Home") %> # "Home"という文字列と:titleというラベルを関連付ける
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> # テンプレートのその部分に実際のタイトルが挿入される
  </head>
  .
  .
  .
</html>
```


## テストの概要
### テスト駆動開発(TDD)
テスト駆動開発のサイクル
1. <font color="red">RED</font> / 失敗するテストを最初に書く
2. <font color="ForestGreen">GREEN</font> / 次にアプリケーションのコードを書いて成功させる (パスさせる)
3. REFACTOR / 必要ならリファクタリングする


<h3 id="guide_line">「テスト駆動」にするか「一括テスト」にするかを決める目安となるガイドライン</h3>

- アプリケーションのコードよりも明らかにテストコードの方が短くシンプルになる (=簡単に書ける) のであれば、「先に」書く
- 動作の仕様がまだ固まりきっていない場合、アプリケーションのコードを先に書き、期待する動作を「後で」書く
- セキュリティが重要な課題またはセキュリティ周りのエラーが発生した場合、テストを「先に」書く
- バグを見つけたら、そのバグを再現するテストを「先に」書き、回帰バグを防ぐ体制を整えてから修正に取りかかる
- すぐにまた変更しそうなコード (HTML構造の細部など) に対するテストは「後で」書く
- リファクタリングするときは「先に」テストを書く。特に、エラーを起こしそうなコードや止まってしまいそうなコードを集中的にテストする

## テスト用設定

### minitest reporters

1, Gemを追加する(Gemfile)

```
source 'https://rubygems.org'

gem 'rails',        '5.1.4'
  .
  .
  .
group :test do
  gem 'rails-controller-testing', '1.0.2'
  gem 'minitest-reporters',       '1.1.14' # minitest reporters
  gem 'guard',                    '2.13.0'
  gem 'guard-minitest',           '2.4.4'
end
  .
  .
  .
```

2, テスト用ヘルパーファイルにコードを追加する

```test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters" # minitest reporters
Minitest::Reporters.use! # minitest reporters
  .
  .
  .
```

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

「home.html.erbファイルが変更されたらstatic_pages_controller_test.rbを自動的に実行する」といったことをGuardで設定することができる。

1, Gemを追加する(Gemfile)

```
source 'https://rubygems.org'

gem 'rails',        '5.1.4'
  .
  .
  .
group :test do
  gem 'rails-controller-testing', '1.0.2'
  gem 'minitest-reporters',       '1.1.14'
  gem 'guard',                    '2.13.0' # guard
  gem 'guard-minitest',           '2.4.4' # guard
end
  .
  .
  .
```

2, Guardの初期化

```
bundle exec guard init
```

3, 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
```

4, .gitignoreファイルを更新

```
# See https://help.github.com/articles/ignoring-files for more about
# ignoring files.
#
  .
  .
  .
# Ignore Spring files.
/spring/*.pid
```

5, 新しいターミナルを開き、次のコマンドを実行する

```
bundle exec guard
```
エラーが出る場合は、以下のコードを実行する

```
sudo yum install -y tmux
bundle exec guard
```