Basic 6. 会社に紐づくスタッフの作り方 Staff、リレーションの説明

# 先週の復習
## RESTful APIとは?
???
## MVCとは?
???

Coach: show, edit, update, destroyのページは作れましたか?

## rake routesコマンドの確認
コンソールで

```
rake routes
```
と打ってみよう。

またroutingをシンプルにしよう

```config/routes.rb
get 'companies', to: 'companies#index'
get 'companies/new', to: 'companies#new', as: 'new_company'
get 'companies/:id/edit', to: 'companies#edit', as: 'edit_company'
get 'companies/:id', to: 'companies#show', as: 'company'
patch 'companies/:id', to: 'companies#update'
post 'companies', to: 'companies#create'
delete 'companies/:id', to: 'companies#destroy'
```
この部分を削除して

```rb:config/routes.rb
resources :companies
```

もう一度

```
rake routes
```

で同じものが表示されることを確認してください。


今日は
# 1. 1:Nのリレーションの作り方: 会社に紐づくスタッフの作り方
データに紐づくデータをどのように表現するか。
データベースがなぜ重要かと言うと、データ同士を紐付けるからです。
例えば、世の中の会社の一覧データと世の中の従業員のデータ

データの表現の仕方として、下記のどちらがいいでしょうか?
a. 会社毎にカテゴリ分けされて一つ一つの会社の従業員がわかる
b. 会社のデータと従業員のデータが紐付かないで、それぞれ別に存在する

# 2. IdeaとCommentの関係を考えてみよう

## 2.1. RESTful API for Comment

ネストしたRESTの組み立て方

|HTTP Request|	URL|	アクション|	用途|
|-----------|------------|------------|------------|
|GET|	/ideas/:idea_id/comments |	index|	あるアイデアのすべてのコメントの一覧ページ|
|GET|	/ideas/:idea_id/comments/:id |	show|	id=:idのコメントの詳細ページ|
|GET|	/ideas/:idea_id/comments/new|	new|	あるアイデアに紐づくコメントの新規作成ページ|
|POST|	/ideas/:idea_id/comments|	create|	コメントを作成するアクション|
|GET|	/ideas/:idea_id/comments/:id/edit	|edit|	id=:idのコメントの編集ページ|
|PATCH|	/ideas/:idea_id/comments/:id	|update|	id=:idのコメントの更新アクション|
|DELETE|	/ideas/:idea_id/comments/:id |	destroy|	id=:idのコメントの削除アクション|

* 先週の一般的なRESTful APIのURLの前に/ideas/:idea_idを入れるのがポイント


## 2.2. MVC for Comment 

- app/models/comment.rb
- app/controllers/comments_controller.rb
- app/views/comments/index.html.erb
- config/routes.rb

# 3. 会社に紐づくスタッフ(Staff)を設計してみよう

## 3.1. RESTful API for Staff

ネストしたRESTの組み立て方

|HTTP Request|	URL|	アクション|	用途|
|-----------|------------|------------|------------|
|GET|	? |	index|	ある会社のすべてのスタッフの一覧ページ|
|GET|	? |	show|	id=:idのスタッフの詳細ページ|
|GET|	?  |	new|	ある会社に紐づくスタッフの新規作成ページ|
|POST|  ? |	create|	スタッフを作成するアクション|
|GET|	?	|edit|	id=:idのフタッフの編集ページ|
|PATCH| ?	|update|	id=:idのスタッフの更新アクション|
|DELETE| ? |	destroy|	id=:idのスタッフの削除アクション|

## 3.2. MVC for Staff

- app/models/?
- app/controllers/?
- app/views/?
- config/routes.rb

# 4. 会社に紐づくスタッフのページを実装していこう

<img width="1440" alt="スクリーンショット 2020-04-21 17.48.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496885/b6000096-e1f7-2c17-3020-3441365a2cf0.png">


## 4.1. モデルを作成する

```
rails generate model Staff name:string title:string
rails db:migrate
```

## 4.2. controllerとviewを作成する

ネストしたroutingの書き方はこのように書きます。

```rb:config/routes.rb
# resources :companies
# の行を全て消して下記を追加してください。

resources :companies do
  resources :staffs
end
```

下記のコマンド

```
rake routes
```
で本当に3.1で考えたpathが生成されているかチェックしてください。

次にcontrollerを作ります。

```
rails generate controller staffs
```

```rb:app/controllers/staffs_controller.rb
def index
end
```

viewを追加します。

```erb:app/views/staffs/index.html.erb
<p>スタッフの一覧</p>
```

- rails serverで起動して実際に画面が表示出来るか確認してください。

## 4.3. リレーションの作成

<img width="1440" alt="スクリーンショット 2020-04-21 17.51.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496885/032d59ad-8efa-698d-ac1e-18d1ca3f8a23.png">



### 4.3.1 migrationを作ります。

- マイグレーションとは?

```
rails generate migration AddCompanyIdToStaff company_id:integer
rails db:migrate
```


### 4.3.2 modelに関係を記述します
各ファイルの2行目に下記を追加。

```rb:app/models/staff.rb
belongs_to :company
```

```rb:app/models/company.rb
has_many :staffs
```

** Coachより: 3人称単数形のsを忘れないようにしよう、複数形なのか単数形なのか意識しよう。**

### 4.3.3 controllerを編集します

```rb:app/controllers/staffs_controller.rb
def index
  @company = Company.find(params[:company_id])
  @staffs = @company.staffs
end
```

### 4.3.4 viewを編集します

```erb:app/views/staffs/index.html.erb
<p>スタッフの一覧</p>
<% @staffs.each do |staff| %>
  <p>
  <%= staff.name %>
  <%= staff.title %>
  </p>
<% end %>
```

`app/views/companies/show.html.erb` を開き、一番下に下記を追加します

```erb:app/views/companies/show.html.erb
<p><%= link_to '従業員の一覧', company_staffs_path(@company) %></p>
```


### 4.3.5 ページをロードして従業員の一覧機能が正しく動いているか確認してみよう


# 5. Railsのviewでのpathの組み立て方

- Pathとは、WEBページのリンクのことで、HTMLで言うところのaタグ

```erb
<a href="/companies/1/staffs">従業員の一覧</a>
```

などに変換されます。

```erb
/companies => companies_path
/companies/new => new_company_path
(POST /companies => companies_path )
/companies/:id  => company_path(@company)
/companies/:id/edit  => edit_company_path(@company)
(PATCH /companies/:id => company_path(@company) )
(DELETE /companies/:id => company_path(@company), method: :delete)
```

スタッフの場合を

```
rake routes
```

でチェックしてみよう。
従業員の一覧へのpathがなぜ下記なのか理解できましたか?

```
company_staffs_path(@company)
```


# 6. 新規作成・登録機能

<img width="1440" alt="スクリーンショット 2020-04-21 17.57.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496885/397d5247-4799-f8b0-82c5-3b0269d6435f.png">



- スタッフを新規作成 'companies/:id/staffs/new', to: 'staffs#new'
- スタッフを登録 POST 'companies/:id/staffs', to: 'staffs#create'

```rb:app/controllers/staffs_controller.rb
def new
  @company = Company.find(params[:company_id])
  @staff = @company.staffs.build
end

def create
  @company = Company.find(params[:company_id])
  @staff = Staff.new(staff_params)
  if @staff.save
    redirect_to company_staffs_path(@company)
  end
end

def staff_params
  params.require(:staff).permit(:name, :title, :company_id)
end
```

```erb:app/views/staffs/new.html.erb
app/views/comments/new.html.erbをコピペして編集してみよう

その時に
app/views/comments/_formもコピペする必要があるのでしよう
```

```erb:app/views/staffs/_form.html.erb
<%= form_with(model: [@company, staff], local: true) do |form| %>
  ...ここの中身を埋めていこう
<% end %>
```

Coach: @companyや@staffのような、controllerのinstance変数とviewのinstance変数は同じものであることを説明しよう。データを表示したければ、そのinstanceを使ってデータをviewで表示しなければならない。controllerからviewにデータを受け渡す場合、決まりとして@を使わなければいけない。(@なしのcompanyやstaffは使えない)。_form.html.erbのstaffはview同士で受け渡しているので@が必要ない。

Coach: 何故form_forで２つのモデルを入れるのか。Railsの決まりです。将来的には自分たちで調べながら実装する必要があります。下記参考。
https://guides.rubyonrails.org/form_helpers.html
https://apidock.com/rails/v5.2.3/ActionView/Helpers/FormHelper/form_for
https://www.w3schools.com/html/html_form_input_types.asp
https://api.rubyonrails.org/v5.1/classes/ActionView/Helpers/FormHelper.html

***7,8は宿題***

# 7. 編集・更新機能

<img width="1440" alt="スクリーンショット 2020-04-21 17.57.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496885/fc574ea0-a9e7-4002-d84e-ff6cab3ed424.png">



- スタッフの編集 'companies/:id/staffs/:id/edit', to: 'staffs#edit'
- スタッフを更新  PATCH 'companies/:id/staffs/:id', to: 'staffs#update'

```rb:app/controllers/staffs_controller.rb
def edit
  @company = Company.find(params[:company_id])
  @staff = Staff.find(params[:id])
end

def update
  @company = Company.find(params[:company_id])
  @staff = Staff.find(params[:id])
  if @staff.update(staff_params)
    redirect_to company_staffs_path(@company)
  end
end
```

```erb:app/views/staffs/edit.html.erb
app/comments/edit.html.erbをコピペして編集してみよう
```

# 8. 詳細機能・削除機能

<img width="1440" alt="スクリーンショット 2020-04-21 17.59.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496885/12730fc7-8fcc-ee98-24dd-e1af484bc62c.png">



- スタッフの詳細を表示 'companies/:id/staffs/:id', to: 'staffs#show'
- スタッフを削除  DELETE 'companies/:id/staffs/:id', to: 'staffs#destroy'


```rb:app/controllers/staffs_controller.rb
def show
  @company = Company.find(params[:company_id])
  @staff = Staff.find(params[:id])
end

def destroy
  @company = Company.find(params[:company_id])
  @staff = Staff.find(params[:id])
  if @staff.destroy
    redirect_to company_staffs_path(@company)
  end
end
```

```erb:app/views/staffs/show.html.erb
app/comments/show.html.erbをコピペして編集してみよう
削除のリンクを追加してみよう
```

# Routingについての詳しい解説を知りたい人は
詳しい説明は下記にあります。
https://railsguides.jp/routing.html


# 3.1の答え*

|HTTP Request|	URL|	アクション|	用途|
|-----------|------------|------------|------------|
|GET|	'companies/:company_id/staffs' |	index|	ある会社のすべてのスタッフの一覧ページ|
|GET|	'companies/:company_id/staffs/:id' |	show|	id=:idのスタッフの詳細ページ|
|GET|	'companies/:company_id/staffs/new'  |	new|	ある会社に紐づくスタッフの新規作成ページ|
|POST|  'companies/:company_id/staffs' |	create|	スタッフを作成するアクション|
|GET|	'companies/:company_id/staffs/:id/edit'	|edit|	id=:idのフタッフの編集ページ|
|PATCH| 'companies/:company_id/staffs/:id'	|update|	id=:idのスタッフの更新アクション|
|DELETE|'companies/:company_id/staffs/:id' |	destroy|	id=:idのスタッフの削除アクション|



# Routingの確認の仕方*

```
rake routes
```


# 6.のviewのファイル 

```erb:app/views/staffs/new.html.erb
<h1>New Staff</h1>

<%= render 'form', staff: @staff %>

<%= link_to 'Back', company_staffs_path(@company) %>
```

```erb:app/views/staffs/_form.html.erb
<%= form_with(model: [@company, staff], local: true) do |form| %>
  <% if staff.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(staff.errors.count, "error") %> prohibited this staff from being saved:</h2>

      <ul>
      <% staff.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name  %>
  </div>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <%= form.hidden_field :company_id, value: @company.id %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>
```

# 7. のviewファイル

```erb:app/views/staffs/edit.html.erb
<h1>Editing Staff</h1>

<%= render 'form', staff: @staff %>

<%= link_to 'Show', company_staff_path(@company, @staff) %> |
<%= link_to 'Back', company_staffs_path(@company) %>
```

# 8. のviewファイル

```erb:app/views/staffs/show.html.erb
<p>
  <strong>Name:</strong>
  <%= @staff.name %>
</p>

<p>
  <strong>Title:</strong>
  <%= @staff.title %>
</p>

<p>
  <strong>Company:</strong>
  <%= @staff.company.name %>
</p>

<%= link_to 'Edit', edit_company_staff_path(@company, @staff) %> |
<%= link_to 'Back', company_staffs_path(@company) %>
```

削除リンクの追加

```erb:app/views/staffs/show.html.erb
<%= link_to 'Destroy', company_staff_path(@company, @staff), data: { confirm: 'Are you sure?' }, method: :delete %> 
```