ウィザード形式でユーザ登録のフォームを作成してみた①　〜テーブルとルーティング〜

## 【この記事の説明】
現在、私はプログラミングスクールでプログラミング（主にRuby）の勉強をしています。
そして、その一環でチーム開発（メルカリもどきのサイト作成）を行っており、私はその中で記事のタイトルにあるように、ウィザード形式でユーザの登録ができるようにする作業を担当致しました。
又、スクールからの指示で、この登録フォームにはdeviseを使用するようにとのことでした。

この記事は、その担当作業についてまとめたものになります。
(記事はいくつかに分けて投稿したいと思います)

下記より、まとめを掲載致しますので、ご覧頂ければ幸いです。

## 【ウィザードとは】
コンピュータからの質問に答えることで物事が進んでいく方式のこと
#### ウィザード形式フォームとは
登録内容ごとにページを分けるフォームのこと

## 【今回作成したユーザ登録フォームとは】
今回作成した登録フォームはウィザード形式で3ページ分の入力をユーザにしてもらうフォームで、ページ毎にデータ保存される（データベースの）テーブルも異なるものとなっています<br>
＜１ページ目＞
**ユーザ情報**
ニックネーム
メールアドレス
パスワード
確認用パスワード
ユーザの本名
ユーザの本名（カナ）
生年月日
<br>
＜２ページ目＞
**ユーザー本人の住所**
郵便番号
都道府県
市区町村
番地
マンションなどの部屋番号
<br>
＜３ページ目＞
**お届け先住所**
届け先の名前
郵便番号
都道府県
市区町村
番地
マンションなどの部屋番号
電話番号

## 【作業】
ここから私が行った作業を記事として記載していこうと思います
※この記事では、必要なテーブルの作成とルーティングを記載したいと思います

### 登録フォーム（haml,scss）を作成←別のチームメンバーが担当<br>
登録フォームの基本形はチームメンバーの方が作成してくれました。
私はその作成されたフォームを使用してデータ保存ができるようにした形になります。

### データベースのテーブル作成
私たちが作成したウィザード形式の登録フォームはページ毎に異なるテーブルにデータが保存されるようになっています
今回作成したウィザード形式は3ページ。つまり、テーブルは３つということになります。<br>
今回作成したテーブルは
1ページ目の情報を保存する→**Userテーブル**
2ページ目の情報を保存する→**Profileaddressテーブル**
3ページ目の情報を保存する→**Deliveryaddressテーブル**

##### ｟テーブルの作成方法｠
※今回はあくまで私の作業担当のところしか記事にしません。ですので、rails newなどに関しては記載致しません。

**＜deviseの導入＞**
1. Gemfileにgem 'devise'を記載する<br>その際、記載するのはGemfile内の一番下をお勧めします<br>間違ってgroup:test do~end内とかに記載するとtest環境でしか使用できないとかがある為です
2. コンソールで下記のコマンドを実行する

```console
% bundle install
% rails g devise:install
% rails g devise user
```
※ここで重要なことはUserテーブルはdeviseで作成したということです

**＜他２つのテーブル作成＞**

```console:ターミナル
% rails g model Profieladdress
% rails g model Deliveryaddress
```
このテーブルはdeviseでは作成せず、rails g model で作成します

#### カラムの作成方法
テーブルは作成できましたが今のままでは、何のデータも入らないテーブルが３つできただけです
ということで、テーブルにカラムを作成します

```console:ターミナル
% rails g devise user
% rails g model Profieladdress
% rails g model Deliveryaddress
```
上記のコマンド実行時に、マイグレーションファイルが一緒に作成されているので、そこに必要なカラムを追加していきます

```ruby:Userテーブル
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      # 元々あるカラム↓
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      # 追加したカラム↓
      t.string :nickname,           null: false
      t.string :family_name,        null: false
      t.string :given_name,         null: false
      t.string :family_name_kana,   null: false
      t.string :given_name_kana,    null: false
      t.date   :birthday,           null: false
      
      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    
  end
end

```
下記の２つのマイグレーションには
```t.references :user,  foreign_key: true
```の記述があります
これは、Userテーブルに紐づくテーブルであることを意味します
ウィザード形式でユーザ登録をする上では重要な部分だと私は思っています

```ruby:Profileaddressテーブル
class CreateProfileaddresses < ActiveRecord::Migration[5.2]
  def change
    create_table :profileaddresses do |t|
      t.string     :postal_code
      t.string     :prefectures
      t.string     :city
      t.string     :address
      t.string     :building
      t.references :user,  foreign_key: true

      t.timestamps
    end
  end
end
```
```ruby:Deliveryaddressテーブル
class CreateDeliveryaddresses < ActiveRecord::Migration[5.2]
  def change
    create_table :deliveryaddresses do |t|
      t.string      :family_name,       null: false
      t.string      :given_name,        null: false
      t.string      :family_name_kana,  null: false
      t.string      :given_name_kana,   null: false
      t.string      :postal_code,       null: false
      t.string      :prefectures,       null: false
      t.string      :city,              null: false
      t.string      :address,           null: false
      t.string      :building
      t.string      :phone_number
      t.references  :user,             foreign_key: true

      t.timestamps
    end
  end
end
```
※:postal_code、:phone_numberは最初、integer型の予定でしたが、:phone_numberは0を認識させたい為に、:postal_codeは正規表現でバリデーションをかける為にstring型に変更しました

``` console:ターミナル
% rails db:migrate
```
マイグレーションファイルの内容（テーブルのカラム）を設定したら、ファイルを反映させる

#### モデルでバリデーション&アソシエーションの設定
記述が長くなるので、別の記事に記載と思います
そちらをお読みください
アソシエーションについて→[ウィザード形式でユーザ登録のフォームを作成してみた②-2　〜viewとcontroller〜](https://qiita.com/niisan3211/items/1c3b86db778552bb9df6)
バリデーションについて→[ウィザード形式でユーザ登録のフォームを作成してみた③-1　〜バリデーション〜](https://qiita.com/niisan3211/items/1871a9d9bf336856424e)

#### deviseでコントローラの作成
deviseのusersコントローラを作成します

```console:ターミナル
% rails g devise:controllers users
```
これで、コントローラは作成できました。
ですが、このままだと以下のようにdevise管理下のコントローラが呼ばれてしまいます

```console:ターミナル
 Prefix Verb   URI Pattern                                                                              Controller#Action
                     root GET    /                                                                                        products#index
         new_user_session GET    /users/sign_in(.:format)                                                                 devise/sessions#new
             user_session POST   /users/sign_in(.:format)                                                                 devise/sessions#create
     destroy_user_session DELETE /users/sign_out(.:format)                                                                devise/sessions#destroy
        new_user_password GET    /users/password/new(.:format)                                                            devise/passwords#new
       edit_user_password GET    /users/password/edit(.:format)                                                           devise/passwords#edit
            user_password PATCH  /users/password(.:format)                                                                devise/passwords#update
                          PUT    /users/password(.:format)                                                                devise/passwords#update
                          POST   /users/password(.:format)                                                                devise/passwords#create
 cancel_user_registration GET    /users/cancel(.:format)                                                                  devise/registrations#cancel
    new_user_registration GET    /users/sign_up(.:format)                                                                 devise/registrations#new
   edit_user_registration GET    /users/edit(.:format)                                                                    devise/registrations#edit
        user_registration PATCH  /users(.:format)                                                                         devise/registrations#update
                          PUT    /users(.:format)                                                                         devise/registrations#update
                          DELETE /users(.:format)                                                                         devise/registrations#destroy
                          POST   /users(.:format)                                                                         devise/registrations#create
           logout_mypages GET    /mypages/logout(.:format)                                                                mypages#logout
             card_mypages GET    /mypages/card(.:format)                                                                  mypages#card
          newcard_mypages GET    /mypages/newcard(.:format)                                                               mypages#newcard
                  mypages GET    /mypages(.:format)                                                                       mypages#index
                 products GET    /products(.:format)                                                                      products#index
              new_product GET    /products/new(.:format)                                                                  products#new
             edit_product GET    /products/:id/edit(.:format)                                                             products#edit
                  product GET    /products/:id(.:format)                                                                  products#show
       rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```

ここで、以下のようにdevise部分のルーティングを設定します

```ruby:routes.rb
Rails.application.routes.draw do 
  root to: 'products#index'
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
  }
  devise_scope :user do
    post  '/profileaddresses', to: 'users/registrations#new_profileaddresses'
    post  '/deliveryaddresses',to: 'users/registrations#new_deliveryaddresses'
  end
   
  resources :mypages, only: [:index] do
    collection do
      get 'logout'
      get 'card'
      get 'newcard'
    end
  end

  resources :products, only: [:index, :new, :edit, :show]
end

```
このように設定後、```rails routes```で確認するとdevise/registrations#xxxとなっていたところが、users/registrations#xxxとなっていることがわかります
つまり、ここでお伝えしたいのは、

```ruby
devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
  }
```
を記述することで、```users/registrations#xxx```,```users/sessions#xxx```となることです

```console:ターミナル
 Prefix Verb   URI Pattern                                                                              Controller#Action
                     root GET    /                                                                                        products#index
         new_user_session GET    /users/sign_in(.:format)                                                                 users/sessions#new
             user_session POST   /users/sign_in(.:format)                                                                 users/sessions#create
     destroy_user_session DELETE /users/sign_out(.:format)                                                                users/sessions#destroy
        new_user_password GET    /users/password/new(.:format)                                                            devise/passwords#new
       edit_user_password GET    /users/password/edit(.:format)                                                           devise/passwords#edit
            user_password PATCH  /users/password(.:format)                                                                devise/passwords#update
                          PUT    /users/password(.:format)                                                                devise/passwords#update
                          POST   /users/password(.:format)                                                                devise/passwords#create
 cancel_user_registration GET    /users/cancel(.:format)                                                                  users/registrations#cancel
    new_user_registration GET    /users/sign_up(.:format)                                                                 users/registrations#new
   edit_user_registration GET    /users/edit(.:format)                                                                    users/registrations#edit
        user_registration PATCH  /users(.:format)                                                                         users/registrations#update
                          PUT    /users(.:format)                                                                         users/registrations#update
                          DELETE /users(.:format)                                                                         users/registrations#destroy
                          POST   /users(.:format)                                                                         users/registrations#create
         profileaddresses POST   /profileaddresses(.:format)                                                              users/registrations#new_profileaddresses
        deliveryaddresses POST   /deliveryaddresses(.:format)                                                             users/registrations#new_deliveryaddresses
           logout_mypages GET    /mypages/logout(.:format)                                                                mypages#logout
             card_mypages GET    /mypages/card(.:format)                                                                  mypages#card
          newcard_mypages GET    /mypages/newcard(.:format)                                                               mypages#newcard
                  mypages GET    /mypages(.:format)                                                                       mypages#index
                 products GET    /products(.:format)                                                                      products#index
              new_product GET    /products/new(.:format)                                                                  products#new
             edit_product GET    /products/:id/edit(.:format)                                                             products#edit
                  product GET    /products/:id(.:format)                                                                  products#show
       rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```
#### ルーティングのカスタマイズ
次に、```devise_scope :user do```の部分についてです
ウィザード形式で3ページの入力ページを作成しているので、newアクションだけでは足りません。
その為、new_profileaddressesアクションとnew_deliveryaddressesアクションを作成し、そのルーティングを```devise_scope :user do```によって行っています

```ruby
devise_scope :user do
    post  '/profileaddresses', to: 'users/registrations#new_profileaddresses'
    post  '/deliveryaddresses',to: 'users/registrations#new_deliveryaddresses'
end
```

又、なぜPOSTのみルーティングしているのかですが、GETのルーティングが必要ないからです
↓
viewからnew_profileaddressesアクション,new_deliveryaddressesアクションにデータを送ることがある→POSTは必要
railsは、アクション後にそのアクション内でどこかに飛ぶ記述がなければ、そのアクション名と同じ名前のviewに飛ぶようになっている→GETは不必要
詳しくは、次の記事でcontrollerのコードを記載しているので確認してください


###【次の記事】
この記事では、テーブル作成とルーティング（devese/→users/）について記述しました。
次の記事ではviewとcontrollerについて記載をしたいと思います

**次の記事** → [ウィザード形式でユーザ登録のフォームを作成してみた②-1　〜viewとcontroller〜](https://qiita.com/niisan3211/items/db15e8bf82a9d7529b5d)


## 【参考資料】
[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word1541.html)
[ウィザードフォーム形式フォームの実装 -devise×session×データを複数テーブルに分けて保存 ver.- (rails)](https://qiita.com/hrwtrhnk/items/657375db8b6b79bc35e0)