devise導入

# 初学者の備忘録
初学者の備忘録です。今回はdevise編


## deviseとは
railsで作ったwebアプリケーションに簡単に認証機能を実装できるgemのことです。
ログイン、ログアウトなどが簡単にできるようになります。


## 導入
【１】　Gem
deviseはGemなのでGemファイルに記述します。一番最後の行で大丈夫です。
```ruby:Gemfile
gem 'devise'
```


【２】　インストール
Gemfile という設計書に書いた内容を、Rails アプリケーションで使えるようにするためのコマンド、bundle installします。
`$ bundle install`


【３】　deviseインストール
Gemを使用可能にするためにbundle installしました。他のGemであればこれだけで大丈夫なのですが、deviseに関しては動作させるためのインストールもしなければいけません。
`$ rails g devise:install`
```ruby:ターミナル
Running via Spring preloader in process 16068
    create  config/initializers/devise.rb
    create  config/locales/devise.en.yml
===============================================================================

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
      is an example of default_url_options appropriate for a development environment
      in config/environments/development.rb:

        config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

      In production, :host should be set to the actual host of your application.

      * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
      For example:

        root to: "home#index"

      * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
      For example:

        <p class="notice"><%= notice %>

        <p class="alert"><%= alert %>


      * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

        rails g devise:views

      * Not required *'

===============================================================================

```
こんな風にターミナルに表示されていれば正常にインストール成功しています。

以上でdeviseの導入は終了です。お疲れ様でした。


## deviseの基本操作
deviseはモデル、ビュー、コントローラを作成するための独自のコマンドを持っています。
複数権限の場合はここの基本操作とはまた少し違います。[devise複数権限編](https://qiita.com/Kooszs12/items/f42985819844041e0275)でご確認ください。

 【１】 Model作成

```ruby:ターミナル
$ rails g devise モデル名
```
複数のModelファイルが作成されます。今回はUserで作成した場合です。
```ruby:ターミナル
username:~/environment/meshiterro $ rails g devise User
Running via Spring preloader in process 4704
      invoke  active_record
      create    db/migrate/20180909134236_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users
```

deviseのapp/models/user.rbファイルを確認すると
```ruby:app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
```
このようなdeviseで利用する機能が記述されています。
必要ない機能も記述されていますが、デフォルトなので特に変更する必要はないです。
<details>
  <summary>補足</summary>
  
「:database_authenticatable, :registerable,」のように、devise の後ろに :（コロン）で始まる部分が devise の機能名です。

:database_authenticatable（パスワードの正確性を検証）
:registerable（ユーザ登録や編集、削除）
:recoverable（パスワードをリセット）
:rememberable（ログイン情報を保存）
:validatable（email のフォーマットなどのバリデーション）
    
</details>

ユーザーテーブルも確認します。
```ruby:db/migrate/（年月日時分秒）_devise_create_users.rb
# frozen_string_literal: true

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: ""

## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at

## Rememberable
t.datetime :remember_created_at

## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip

## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable

## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at


t.timestamps null: false
end

add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
```
デフォルトで作成されます。ですが、デフォルトのままだとemailとpasswordのみのサインアップ、サインイン機能になります。
それだけで十分でしたらこのままでもいいのですが、例えばサインアップの時に名前や住所も入力したいなどアレンジを加えたい場合、別途対応しなければなりません。


【２】　Viewの作成
必要なViewファイルを作成します。
```ruby:ターミナル
$ rails g devise:views

Running via Spring preloader in process 4970
invoke Devise::Generators::SharedViewsGenerator
create app/views/devise/shared
create app/views/devise/shared/_links.html.erb
invoke form_with
create app/views/devise/confirmations
create app/views/devise/confirmations/new.html.erb
create app/views/devise/passwords
create app/views/devise/passwords/edit.html.erb
create app/views/devise/passwords/new.html.erb
create app/views/devise/registrations
create app/views/devise/registrations/edit.html.erb
create app/views/devise/registrations/new.html.erb
create app/views/devise/sessions
create app/views/devise/sessions/new.html.erb
create app/views/devise/unlocks
create app/views/devise/unlocks/new.html.erb
invoke erb
create app/views/devise/mailer
create app/views/devise/mailer/confirmation_instructions.html.erb
create app/views/devise/mailer/email_changed.html.erb
create app/views/devise/mailer/password_change.html.erb
create app/views/devise/mailer/reset_password_instructions.html.erb
create app/views/devise/mailer/unlock_instructions.html.erb
```
rails g devise:views コマンドによって作成される View は、devise のさまざまな機能と関連付けられています。
ここまでで自動的にサインアップ、サインインフォームは完成しています。
![スクリーンショット 2023-09-21 18.17.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/9c4de61c-6e7f-ad7f-6f9e-44c12f8c1ffa.png)


【３】　フォームヘルパー修正
deviseで提供される画面では、フォームを作成するヘルパーとしてform_forが使用されています。form_forは現在は非推奨ですので、form_withへと変更します。
変更するファイルはユーザー登録画面とログイン画面です。
```diff_ruby:app/views/devise/registrations/new.html.erb
<h2>Sign up</h2>

-<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
+<%= form_with model: @user, url: user_registration_path do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
  <%= f.label :name %><br>
  <%= f.text_field :name, autofocus: true %>
</div>

:
:
```
```diff_ruby:app/views/devise/sessions/new.html.erb
<h2>Log in</h2>

-<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
+<%= form_with model: @user, url: user_session_path do |f| %>
<div class="field">
  <%= f.label :email %><br>
  <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

:
:
```
絶対に修正しなければいけないというわけではありませんが、修正しておいた方がいいでしょう。


## 最後に
今回は基本的なことしか書いていませんが、この他にも入力フォームのカスタマイズ、ゲストログイン、退会機能あたりがdeviseを利用して出来る機能で使用頻度が高いので別途備忘録として投稿していきたいと思います。

- [入力フォームカスタマイズ](https://qiita.com/Kooszs12/items/32afcecf1053ccf54b2c)