先週の復習
RESTful APIとは?
???
MVCとは?
???
Coach: show, edit, update, destroyのページは作れましたか?
rake routesコマンドの確認
コンソールで
rake routes
と打ってみよう。
またroutingをシンプルにしよう
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'
この部分を削除して
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. 会社に紐づくスタッフのページを実装していこう
 
4.1. モデルを作成する
rails generate model Staff name:string title:string
rails db:migrate
4.2. controllerとviewを作成する
ネストしたroutingの書き方はこのように書きます。
# resources :companies
# の行を全て消して下記を追加してください。
resources :companies do
  resources :staffs
end
下記のコマンド
rake routes
で本当に3.1で考えたpathが生成されているかチェックしてください。
次にcontrollerを作ります。
rails generate controller staffs
def index
end
viewを追加します。
<p>スタッフの一覧</p>
- rails serverで起動して実際に画面が表示出来るか確認してください。
4.3. リレーションの作成
 
4.3.1 migrationを作ります。
- マイグレーションとは?
rails generate migration AddCompanyIdToStaff company_id:integer
rails db:migrate
4.3.2 modelに関係を記述します
各ファイルの2行目に下記を追加。
belongs_to :company
has_many :staffs
** Coachより: 3人称単数形のsを忘れないようにしよう、複数形なのか単数形なのか意識しよう。**
4.3.3 controllerを編集します
def index
  @company = Company.find(params[:company_id])
  @staffs = @company.staffs
end
4.3.4 viewを編集します
<p>スタッフの一覧</p>
<% @staffs.each do |staff| %>
  <p>
  <%= staff.name %>
  <%= staff.title %>
  </p>
<% end %>
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タグ
<a href="/companies/1/staffs">従業員の一覧</a>
などに変換されます。
/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. 新規作成・登録機能
 
- スタッフを新規作成 'companies/:id/staffs/new', to: 'staffs#new'
- スタッフを登録 POST 'companies/:id/staffs', to: 'staffs#create'
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
app/views/comments/new.html.erbをコピペして編集してみよう
その時に
app/views/comments/_formもコピペする必要があるのでしよう
<%= 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で2つのモデルを入れるのか。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. 編集・更新機能
 
- スタッフの編集 'companies/:id/staffs/:id/edit', to: 'staffs#edit'
- スタッフを更新 PATCH 'companies/:id/staffs/:id', to: 'staffs#update'
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
app/comments/edit.html.erbをコピペして編集してみよう
8. 詳細機能・削除機能
 
- スタッフの詳細を表示 'companies/:id/staffs/:id', to: 'staffs#show'
- スタッフを削除 DELETE 'companies/:id/staffs/:id', to: 'staffs#destroy'
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
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のファイル
<h1>New Staff</h1>
<%= render 'form', staff: @staff %>
<%= link_to 'Back', company_staffs_path(@company) %>
<%= 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ファイル
<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ファイル
<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) %>
削除リンクの追加
<%= link_to 'Destroy', company_staff_path(@company, @staff), data: { confirm: 'Are you sure?' }, method: :delete %>