【Ruby on Rails】退会機能をgemなしで実装する方法


#対象者

* 退会機能を実装予定の方


#目的

* 退会機能を実装して退会後、ログイン出来ないようにする

#実際の手順と実例
###1.deviseの導入

User認証で新規登録とログインを行うためにdeviseを導入します

https://qiita.com/nao0725/items/83c73c417be01913a857

```Gemfile.
gem 'devise'
```

````Terminal.
$ bundle install
$ rails g devise:install
$ rails g devise user　name:string　is_valid:boolean #①
$ rails g devise:views
````

①で退会したかどうかを判断するカラムを作成しています。
booleanは真偽のどちらの値なのかを決めるデータ型です。

https://techacademy.jp/magazine/42560

boolean型はデフォルト値を設定する必要があるので、マイグレーションファイルを編集します。


```db/migrate/20210815082848_add_is_valid_to_users.rb
class AddIsValidToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :is_valid, :boolean, default: true, null: false
  end
end
```

デフォルト値がtrue（有効）に設定しているのでfalseが退会している状態を表しています。

```Terminal.
$ rails db:migrate
````

実行後下記のようにテーブルが作成されます。

```db/schema.rb
 create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.string "name"
    t.boolean "is_valid", default: true, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end
```


###2.コントローラーの設定

Homes_Controllerに作成していきます。

```app/controllers/homes_controller.rb
  def unsubscribe #退会画面
    @user = current_user
  end

  def withdraw #退会処理
    @user = User.find(params[:id])
    @user.update(is_valid: false) #falseにすることで退会済に変更
    reset_session
    redirect_to root_path, alert: "ご利用誠にありがとうございました。"
  end
```

続いて退会済のUserが再ログインできないようにSessions_Controller に設定していきます。

````app/controllers/users/sessions_controller.rb 
before_action :reject_user, only: [:create]

:
(中略)
:

 # 退会後のログインを阻止
  def reject_user
    @user = User.find_by(name: params[:user][:name])
    if @user
      if @user.valid_password?(params[:user][:password]) && (@user.active_for_authentication? == false)
        flash[:error] = "退会済みです。"
        redirect_to new_user_session_path
      end
    else
      flash[:error] = "必須項目を入力してください。"
    end
  end
````


###3.ルーティングの設定

````config/routes.rb
    get "unsubscribe/:name" => "homes#unsubscribe", as: "confirm_unsubscribe"
    patch ":id/withdraw/:name" => "homes#withdraw", as: "withdraw_user"
    put "withdraw/:name" => "users#withdraw"
````

###4.Viewの設定

```app/views/homes/unsubscribe.html.erb

<div class = "container">
   <div class = "title text-center">本当に退会しますか？</div>
   <div class = "card unsub-text">
     <div class = "row justify-content-center">
       <div class = "text-center">
         <p class = "py-3">
           退会すると、会員登録情報が閲覧できなくなります。<br>
           退会する場合は『退会する』をクリックしてください。
          </p>
          <div class = "row unsub-text mt-3">
          <div class = "no-delete">
            <%= link_to "退会する", withdraw_user_path(@user), method: :patch, data: { confirm: '本当に退会しますか？' }, class: "btn btn-outline-danger btn-sm " %>
          </div>
          <div class = "float-right">
            <%= link_to "退会しない", user_path(@user), class: "btn btn-outline-primary btn-sm" %>
          </div>
          </div>
       </div>
     </div>
   </div>
</div>

````

※bootstrap4を使用しています。


````applicaiton.scss

// 退会機能
.unsub-text {
    text-align: center;
    margin: 50px;
}

.no-delete {
    margin-left: 50px;
    margin-right: 100px;
    text-align: center;
}

````

これで実装完了です！


#参照

* [Rubyでbooleanの判定を行う方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/42560)