Railsチュートリアル(第6版)　第2章　Toyアプリケーション

##第２章
第１章では、AWS Cloud9でRubyを使うための環境構築、Githubにリモートプッシュ、Herokuにデプロイを行った。
第２章では、`scaffold`というスクリプトを使って簡単にCRUD機能を持ったアプリケーションを作成する。また、RESTアーキテクチャについて触れていく。

##Toy\_app
・流れ
toy_app作成→Gemfile設定→gemインストール→Git管理下に配置→リモートレポジトリにプッシュ

①先ずは、新たに`toy_app`アプリを生成

```
$ cd ~/environment
$ rails _6.0.3_ new toy_app　←railsチュートリアルは基本的にバージョン指定
$ cd toy_app/
```

②Gemfileを設定する。

```ruby:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.6'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

group :development, :test do
  gem 'sqlite3', '1.4.1'
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

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

group :test do
  gem 'capybara',           '3.28.0'
  gem 'selenium-webdriver', '3.142.4'
  gem 'webdrivers',         '4.1.2'
end

group :production do
  gem 'pg', '1.1.4'
end

# Windows ではタイムゾーン情報用の tzinfo-data gem を含める必要があります
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
```

railsチュートリアルをしていると`Gemfile`というファイルをよく使います。
Q：Gemfileとは？
A：gemの一覧を記載しているファイルのこと。因みに`gem`は`ruby`のライブラリのこと

③gemのインストール

```
$ bundle install --without production
```

`--without production`とすることで本番環境を除いたgemをインストールできる。

④Toy_appをGitのバージョン管理下に置く。

```
$ git init
$ git add -A
$ git commit -m "Initialize repository"
```

⑤リモートリポジトリにプッシュ

```
$ git remote add origin https://github.com/<あなたのGitHubアカウント名>/toy_app.git
$ git push -u origin master
```

ここまで出来れば準備完了。

第１章と同様に`hello world`と表示する。

・コントローラーとアクションの設定

```ruby:application_controller.rb
class ApplicationController < ActionController::Base

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

<details><summary>MVCのViewはどこ？</summary><div>

MVCのViewはどこかという話ですが、`render html: "hello, world!"`の箇所で`render`メソッドを使って描画しています。(本来ならば、Viewファイルを作って呼び出します。)
</div></details>

・ルートルーティングの設定

```ruby:routes.rb
Rails.application.routes.draw do
  root 'application#hello'
end
```

・変更のコミットは、Heroku＆Githubにプッシュ

```
$ git commit -am "Add hello"
$ heroku create
$ git push && git push heroku master
```

`git push && git push heroku master`の一文について、**`&&`**という箇所があるが、**`&&`**で連結すると一つ目のコマンドが成功した場合に限り実行される。
なので、この場合は`github`へのプッシュが出来たら、`heroku`にもプッシュするということ。

##usersモデル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/4c4830ba-3b9e-83bf-78bb-3c478964f9dd.png)
参照：railsチュートリアル第6版

・users → テーブル名(テーブル名は複数形を使うのが慣例)
・id：integer → 一意のid(数字のダブりがない。整数型)
・name：string → 名前(文字列型)
・email：string → 電子メール(文字列型)

id、name、emailは属性と呼びカラム(column)に相当 

<details><summary>カラムとレコードのお話</summary><div>

カラム(column)は列で、レコード(record)は行と言われますが、どちらが縦で横か昔はごっちゃになった事があったので記載。

columnやlineといった単語に`l(エル)`が含まれてますね。そう、こっちが縦です。(日本語だと列)
recordやrowは、`r`がありますね。`R`は横向きに線が生えていますね。(無理やりですが)。こっちが横です。(日本語だと行)
片方覚えればいいと思います。
</div></details>

##micropostsモデル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/c76611db-f256-7449-a4c2-d6718a000de5.png)
参照：railsチュートリアル第6版

`user_id`というのがあるが、これは、usersモデルの`id`と後で結びつく。

<details><summary>stringとtextのお話</summary><div>

ちょうざっくり説明します。
string型 255文字まで
text型 それ以上
</div></details>

##usersリソース
上記でusersテーブルがいきなり出てきたが、ここから`scaffold`を使って、同時にusersテーブルも作成していく。
以下`scaffold`コマンド

```
$ rails generate scaffold User name:string email:string
```
`scaffold`の後に`User`と入力後、`name:string`と`email:string`を追記する。

Q：`scaffold`の後の`User`はなぜ複数形じゃない？
A：`scaffold`の後の`User`はモデル名のため**単数形**を使用する。

できたらデータベースをマイグレートする。

```
$ rails db:migrate
```

データベースマイグレートをすることで、データベースを更新し`users`データモデルを作成するため。

一応hello worldと表示されていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/51e26ce6-9b56-8297-bf0d-139daaf48140.png)


##ユーザーページ
`scaffold`を使ったことで簡単なCRUD機能を持ったページが作られている。
CRUD：CREATE(作成)/READ(読み取り)/UPDATE(更新)/DELETE(削除)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/261cfa36-c1f1-948f-94a9-c9fd65e26339.png)
参照：railsチュートリアル

まずは、`/users`ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/16435cb9-0bf4-3e44-113a-5c74f5cf2c69.png)

`/users/new`ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/93bf60fa-24d0-6d16-feb5-b4578bc10135.png)

ユーザー作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/3de10732-33eb-4d38-6564-a2f9cea986db.png)

`/users/edit`ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/d7ac26f2-57c9-5b8c-a2a6-5f23e22041e1.png)

ユーザーアップデート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/bd70e1ff-c2ce-cd24-eb49-6975cdcc0eb3.png)

`/users/show`ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/596e6f82-5412-fecc-4443-da86ca630e66.png)

`scaffold`でCRUD機能が実装できた。
(`scaffold`は便利ですが、未知数の部分が多いので、基本的に使用せず1からCRUDを作っていきます)

##MVCの動き
MVCの詳しい動作について解説

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/0fb04b9b-11d7-935e-7b76-3f34e8354341.png)
参照：railsチュートリアル

>1.ブラウザから「/users」というURLのリクエストをRailsサーバーに送信する。
2.「/users」リクエストは、Railsのルーティング機構（ルーター）によってUsersコントローラ内のindexアクションに割り当てられる。
3.ndexアクションが実行され、そこからUserモデルに、「すべてのユーザーを取り出せ」（User.all）と問い合わせる。
4.Userモデルは問い合わせを受け、すべてのユーザーをデータベースから取り出す。
5.データベースから取り出したユーザーの一覧をUserモデルからコントローラに返す。
6.Usersコントローラは、ユーザーの一覧を@users変数（@はRubyのインスタンス変数を表す）に保存し、indexビューに渡す。
7.indexビューが起動し、ERB（Embedded RuBy: ビューのHTMLに埋め込まれているRubyコード）を実行して HTMLを生成（レンダリング）する。
8.コントローラは、ビューで生成されたHTMLを受け取り、ブラウザに返す5

railsチュートリアルから引用

・`resources :users`と`root 'users#index'`を設定

```ruby:config/routes.rb
Rails.application.routes.draw do
  resources :users
  root 'users#index'
end
```

`resources :users`は、第４章で触れるので、ここではスルー
`root 'users#index'`は、コントローラー名#アクション名で、`users`コントローラーの`index`アクションを実行する。

では`users`コントローラーの`index`アクションの中身はどうなっているか？は下記のコード(一部省略)

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end
```

まずは、`index`アクションの動作について解説。
`@users = User.all`は、Userモデルにある全レコードを取得し、`@users`に代入するという意味。なおメソッドにおける変数の定義には、@を付けて`@users`のような形でインスタンス変数を定義できる。

<details><summary>インスタンスの簡単な説明</summary><div>

インスタンスは、クラスから生成されたオブジェクトの事。
クラスはインスタンスの型を作るためのもの。

プログラミングの本とか読んでいると、「クラスは、クッキー(お菓子の方)の型を取る道具で、実際に型取られたクッキーがインスタンス！」だとか、「クラスは、自動車の設計図で、それを元に作られた車がインスタンス」とかそんな説明が書いてあります。
</div></details>
なぜ`User.all`が全ユーザーを返すのか。
継承の機能によってUserモデルは、**Active Record**というRubyのライブラリがあるおかげで、`User.all`というリクエストに対し、データベース上の全ユーザーを返してくれる。

次いで、`UsersController`内には、様々なアクションがあると思いますが、これらは`scaffold`で作成されたもの。
第二章は`REST`アーキテクチャの概念についての理解があったので、ここで記載する。

Q：REST(レスト)って？
A：REpresentational State Transferの略。既に幅広く普及したWEBの仕組み(HTTPとか)をそのまま利用して、容易にWEBサービスを可能にするもの。

・usersリソースのREST対応表
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/8d06da96-cbd5-72c0-c3de-1ff8fca06081.png)

`@users`変数に全ユーザーが格納されたら、今度はビューを呼び出す。Railsのコントローラー内でインスタンス変数を宣言したことで、この変数はビューでも使えるようになる。

```Ruby:app/views/users/index.html.erb
    <% @users.each do |user| %>
      <tr>
        <td><%= user.name %></td>
        <td><%= user.email %></td>
        <td><%= link_to 'Show', user %></td>
        <td><%= link_to 'Edit', edit_user_path(user) %></td>
        <td><%= link_to 'Destroy', user, method: :delete,
                         data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
```

1行目に`@users`なるものがあることがわかる。railsチュートリアルでは、このコードの説明は省略しているが、少し説明を加えます。
`@users`に格納されたユーザーに関わるデータを一人ずつ`|user|`に代入して、各ユーザーの名前やメールアドレスを表示するというものです。この作業を人数分繰り返すという訳です。

###Usersリソースの欠点
`scaffold`という便利な機能がありますが、問題点があります。

・データ検証がされない
　→ユーザ名が空白でも、メールアドレスが適当でも通ってしまう。

・ユーザー認証がない
　→誰でも制限なしに操作できる。

・テストがない
　→必要なレベルのテストまでは書かれていない。

・レイアウトやスタイルが整ってない
　→なんかかっこよくない。

・理解が困難
　→`scaffold`は自動であるがゆえに、コード理解が難しい。

###Micropostsリソース
Usersリソースと同様にMicropostsリソースも作成

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

データベースの更新

```
$ rails db:migrate
```


ルーティングの確認

```ruby:config/routes.rb
Rails.application.routes.draw do
  resources :microposts
  resources :users
  root 'users#index'
end
```

`resources :microposts`が`scaffold`で自動で追加され、これにより各アクションに対応するようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/bef938bd-0ec5-c2ec-2487-b85c68b5c4df.png)
参照：railsチュートリアル

次いで、`microposts_controller`の中身も確認(一部省略)

```ruby:app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  before_action :set_micropost, only: [:show, :edit, :update, :destroy]

  # GET /microposts
  # GET /microposts.json
  def index
    @microposts = Micropost.all
  end

  # GET /microposts/1
  # GET /microposts/1.json
  def show
  end

  # GET /microposts/new
  def new
    @micropost = Micropost.new
  end

  # GET /microposts/1/edit
  def edit
  end
```

`UsersController`の中身と同じであることが分かる。

マイクロポストを投稿してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/ead304ca-c717-c0c5-a88c-ebb2c7249e64.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/7ca2a75e-3c97-462a-7d98-05f813045ced.png)

###マイクロポストに制限
現在は投稿する際の文字制限がない。なので、文字数制限を与えてみる。
railsでは、バリデーションという機能を使うことで様々制限を加えられる。

```ruby:app/models/micropost.rb
class Micropost < ApplicationRecord
  validates :content, length: { maximum: 140 }
end
```

このコードは、直感的に見た通りの動作をする。コンテンツの最大長さが140文字という内容をそのまま解釈できる。
コードを実装したので、実際に141以上打ち込んでみると、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/c7e6157b-68aa-8c20-7ee0-ecb1f0814cba.png)


###データモデル同士の関連付け

ユーザーモデルとマイクロポストモデルを関連付ける。

```ruby:app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
end
```


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

・ユーザーモデルは、沢山のマイクロポストを持っているため、`has_many`な関係
・マイクロポストはあるユーザーのみに属しているので、`belongs_to`の関係

①rails console起動

```
ubuntu:~/environment/toy_app (master) $ rails console
Running via Spring preloader in process 9488
Loading development environment (Rails 6.0.3)
```


②最初のユーザーを取得し、`first_user`に格納

```
2.6.3 :001 > first_user = User.first
   (0.4ms)  SELECT sqlite_version(*)
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<User id: 1, name: "名前あり", email: "名前ありメール", created_at: "2021-05-17 22:43:11", updated_at: "2021-05-17 22:44:23"> 
```

③`first_user`に紐づいたマイクロポストを取得

```
2.6.3 :002 > first_user.microposts
  Micropost Load (0.1ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? LIMIT ?  [["user_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "すっごい眠い", user_id: 1, created_at: "2021-05-18 22:31:59", updated_at: "2021-05-18 22:31:59">]> 
```

④`first_user`の最初のマイクロポスト(`microoist id:1`)を`micropost`に代入

```
2.6.3 :003 > micropost = first_user.microposts.first
  Micropost Load (0.2ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
 => #<Micropost id: 1, content: "すっごい眠い", user_id: 1, created_at: "2021-05-18 22:31:59", updated_at: "2021-05-18 22:31:59"> 
```
⑤`mircropost.user`で`User id`が１の人の情報を表示

```
2.6.3 :004 > micropost.user
 => #<User id: 1, name: "名前あり", email: "名前ありメール", created_at: "2021-05-17 22:43:11", updated_at: "2021-05-17 22:44:23"> 
```
`has_many`と`belong_to`を使うことでそれぞれ違ったモデルを結び付けてデータを表示することが出来る。

##継承
railsチュートリアル的に、ここは何となくの理解でもOK

ざっくりと説明
Q：継承って？
A：モデルに親子関係があるよ！子は親のクラスを引き継いで、使用できる。親のできることが、子にもできるようになること。

Rubyでは、継承関係を`<`で表す。

```ruby:app/models/user.rb
class User < ApplicationRecord
```

```ruby:app/models/micropost.rb
class Micropost < ApplicationRecord
```

継承の図式はこのような感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/b8e9820c-c82d-d2f2-da77-7f95cadfabc4.png)
参照：railsチュートリアル

`User`と`Micropost`は`ApplicationRecord`を継承しており、`ApplicationRecord`は`ActiveRecord::Base`を継承している。

このような継承関係は、モデルだけではなくコントローラーも同様である。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
```

```ruby:app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
```

`ApplicationController`は、`ActionController::Base`を継承

```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/d9231676-6a43-dc92-ef01-d56997edd737.png)
参照：railsチュートリアル

継承機能が備わっている事で、子クラスでも親クラスで定義しているルールが適用される。そのため、よく使う共通のルールは、親クラスに作成すると良いって話。

演習の内容確認
1つ目

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    
  def hello
    render html: "hello, world!"
  end
end
```

2つ目

```ruby:app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
```


##デプロイ
第2章の内容をデプロイ

```
$ git status    #追加の前にこうやって状態を確認するのはよい習慣です
$ git add -A
$ git commit -m "Finish toy app"
$ git push
```

Gitコミットはこまめにしておくと良いとのこと。

```
$ git push heroku
```

herokuにもpushして出来たら完了

#おわりに
第二章で学んだ事

・`scaffold`でCRUD機能を作った
・MVCの挙動
・`User`リソースと`Micropost`リソースの結びつけ
・継承関係

第二章までは、ほぼ自動的にCRUDの機能を作ってきましたが、これからは自分でやるため段々と難しくなってきます。