Ruby on Rails_学習2

#### 投稿目的
- 個人的な学習のために投稿しています。
- 暖かい目で閲覧していただけると幸いです。

## Microposts
- Usersリソースと同様にMicropostsリソースも生成していきます。

### Micropostsリソース
- Micropostsリソースもscaffoldでコードを生成してます。
- rails generate scaffoldコマンドを利用します。

```rails
$ rails generate scaffold Micropost content:text user_id:integer
```

- scaffoldコマンドを実行することで必要なルーティング、コントローラなどを自動で生成されます。

### Migrate
- 新しく作成したデータモデルをデータベースに更新するにはマイグレーションを実行します。

```rails
$ rails db:migrate
```

- 上記のコマンドでDBが更新されました。

### Micropostsページ
 
#### localhost:3000/microposts/newでマイクロポスト新規作成ページ
 

 ![Image from Gyazo](https://i.gyazo.com/efe707179939a30c3cae5aca24d0592b.png)
 
#### localhost:3000/micropostsでマイクロポスト一覧ページ
 
 ![Image from Gyazo](https://i.gyazo.com/eaa44618ff756f96723c200d43ef25b2.png)
 
 - 編集、削除などのページも存在します。

### バリデーション(validation)
- バリデーションを使って簡単に制限を加えることができます。
- Twitterのように140文字制限を加えたいときは、lengthを使うだけです。

```rails:micropost.rb
class Micropost < ApplicationRecord
  validates :content, length: { maximum: 140 } # 140文字制限
end
```

### 関連付け
- 異なるデータモデル同士の関連付けは、Railsの強力な機能です。
- UsersとMicropostsを関連付けことで1人のユーザーに対してマイクロポストを複数持つことができます。

```rails:user.rb
class User < ApplicationRecord
  has_many :microposts
end
```

```rails:micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 140 }
end
```

- 上記のようにコードを追加することでmicropostモデルのuser_idとusersモデルのidが関連付けれます。

## 継承
- コントローラの継承構造も、モデルの継承構造と本質的には同じです。UsersコントローラとMicropostsコントローラはいずれもApplicationControllerを継承。
- ApplicationControllerはActionController::Baseというクラスを継承。
- このクラスは、RailsのAction Packというライブラリが提供しているコントローラの基本クラスです。

## 静的なページ(sample_app)作成

### ファイル生成
- まずは、toy_app同様rails newでファイルを生成します。
- 下記のコマンドを実行することで必要なファイルを生成されます。

```rails
$ rails new sample_app
```

### ライブラリインストール
1. gemfileに必要なライブラリを記述します。
2. bundle installコマンドでgemfileに記述したライブラリをインストールします。
    - --withoutオプションを記述してdevelopment(本番環境)/production(開発環境)で環境を指定することができます。
```rails
$ bundle install --without 環境
```

- gemのライブラリのバージョンが異なるものをインストールしている場合はbundle updateを実行してgemを更新しバージョンを合わせます。

```rails
$ bundle update
```

## アプリケーション開発
- 静的なHTMLのみのページを作成しその後、静的なページを動的なページに作り変えていきます。
- アクションはcontroller(コントローラ)に記述します。

### StaticPagesコントローラ生成
- scaffold生成で利用したrails generateを利用しコントローラを生成します。
- rails generateはアクション名もまとめて指定することができます。

```rails
$ rails generate controller StaticPages home help
```

- ファイル名: StaticPages   アクション名: home help
 
- 実行すると下記のように生成されます。

![Image from Gyazo](https://i.gyazo.com/245f1886b943c05d6e1a90c6637bf0d3.png)

## Rails元に戻す機能
- 上記のように [rails generate controller StaticPages] を実行してからやり直した場合は追加されたコードやファイルなどを手動で削除してると手間やバグなどに繋がります、元に戻す場合は [rails destroy] がRailsでは用意されており指定したものを自動で削除します。

```rails
$ rails destroy controller StaticPages
```

- model生成を行なった際でも戻し方は上記と同様でcontrollerをmodelに変更してファイル名です。

#### マイグレーションの変更を元に戻す方法もあります。

```rails
## データベースのマイグレーションを変更します。
$ rails db:migrate

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

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

```

## コマンドの短縮形
- コマンドを短縮して記述することが可能です。
- Railsを利用しているほとんどが短縮形を利用しています。
 
    |完全なコマンド | 短縮形|
    |:-- |:---:|--:|
    |$ rails server	| $rails s|
    |$ rails console	|$ rails c|
    |$ rails generate|	$ rails g|
    |$ rails test	|$rails t|
    |$ bundle install|	$ bundle|

## ルーティング
- rails generate controllerを実行する際にhomeアクションとhelpアクションを追加してルーティングに下記の用にルールが定義されています。
- /static_pages/homeというURLに対するリクエストをGETリクエストで受け取ったときに対応するアクションを結びつけています。
 
```rails
Rails.application.routes.draw do
  get  'static_pages/home'
  get  'static_pages/help'
  root 'application#hello'
end
```

- GETはWeb上のデータを読み取るときに使われます、ページを取得する(get a page)というう意味のとおり、ブラウザなどのWebサイトを開くたびにGETリクエストをサイトに送信します。
- POSTはページ上のフォームに入力した値を、ブラウザから送信する際、何かを作成するときによく使われます、例えばユーザー登録フォームで新しいユーザーを作成するときは、POSTリクエストを送信します。

## StaticPagesController
- <はStaticPagesControllerにApplicationControllerを継承しているという意味です。
- メソッド内はまだ空でRubyはの場合は何も実行されませんがRailsの場合はApplicationControllerを継承しているので、コード実行後にそのアクションに対応するViewを出力します。

```rails:static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
end
```

## テスト
- 何らかの変更を行う際には自動化テストを作成して機能が正しく実装されたかを確認する。
- テストを作成するということは、その分コードを余分に書くことになりますが、正しく行えば、むしろテストがないときよりも確実に開発速度がアップします。テストが揃っていれば、バグを追うために余分な時間を使わずに済むためです。
- テストのメリット
    - テストが揃っていれば、機能停止に陥るような回帰バグ (以前のバグが再発したり機能の追加/変更に副作用が生じたりすること)を防止できる。
    - テストが揃っていれば、コードを安全にリファクタリングができる。
    - テストコードは、アプリケーションコードから見ればクライアントとして動作するので、アプリケーションの設計やシステムの他の部分とのインターフェイスを決めるときにも役に立つ。
- 最初にコントローラやモデルのテストを書き、続いて統合テスト (モデル/ビュー/コントローラにまたがる機能テスト) を書く、ということになります。

## コントローラテスト

### Aboutページ追加
- 最初にAboutページのコントローラテストを作成を行いますが、 [rails generate controller] を実行した際にテストファイルは生成されています。

```rails:test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  test "should get home" do
      ## getで受け取る
    get static_pages_home_url
      ## HTTPステータスコード
    assert_response :success
  end

  test "should get help" do
      ## getで受け取る
    get static_pages_help_url
      ## HTTPステータスコード
    assert_response :success
  end
end
```
- HTTPステータスコードは、HTTPにおいてWebサーバからのレスポンスの意味を表現する3桁の数字からなるコードである。

- getリクエストをhomeアクションに対して送信、そうすれば、リクエストに対するレスポンスは[成功]となるはず、となります。

#### テスト実行
- テストを実行する際は [rails test] コマンドで実行することができます。

#### テスト失敗
- まずはaboutでテストが失敗するコードを上記のファイルに記述します。

```rails: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
    
    ## About追加
  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end

end
```

- ターミナル結果を見るとエラー内容と失敗という結果が返ってきます。

```rails:ターミナル
$ rails test
// 結果
1) Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x00007fe3090da8d8>
   
3 runs, 2 assertions, 0 failures, 1 errors, 0 skips
```

- 上記のエラーメッセージを元に解決をしていきます、内容は「AboutページへのURLが見つからない」となります。
###### 下記のようにルーティング内容を修正します。

```rails:routes.rb
Rails.application.routes.draw do
  get  'static_pages/home'
  get  'static_pages/help'
   ## aboutルートを追加
  get  'static_pages/about'
  root 'application#hello'
end
```
- static_pages/aboutというURLに対してgetリクエストが来たら、StaticPagesコントローラのaboutアクションに渡すようRailsに指示しています。

###### もう一度実行

```rails:ターミナル
$ rails test
// 結果
1) Error:
StaticPagesControllerTest#test_should_get_about:
AbstractController::ActionNotFound: The action 'about' could not be found for StaticPagesController

3 runs, 2 assertions, 0 failures, 1 errors, 0 skips
```

- もう一度実行を行うと、エラー内容が変わり、失敗をています。
- 内容は「StaticPagesコントローラにaboutアクションがない」ということがわかります。

###### aboutアクションを追加します

```rails:static_pages_controller.rb
class StaticPagesController < ApplicationController

  def home
  end

  def help
  end
  ## aboutアクション追加
  def about
  end
end
```

###### もう一度実行

```rails:ターミナル
$ rails test
// 結果
1) Error:
StaticPagesControllerTest#test_should_get_about:
ActionController::UnknownFormat: StaticPagesController#about is missing a template for this request format and variant.

3 runs, 2 assertions, 0 failures, 1 errors, 0 skips
```

- aboutアクションを追加後エラー内容が変わり、失敗しています。
- 次の内容は「表示するためのテンプレートがビューにありません」のようなメッセージです。

###### viewsディレクトリにabout.html.erbファイルを追加

```rails:app/views/static_pages/about.html.erb
<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>
```

- about.html.erbファイル内にコードを記述します。

###### もう一度実行

```rails:ターミナル
$ rails test
// 結果
$ rails test
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
```

- エラーなしで結果は成功になります。