LoginSignup
9
6

More than 1 year has passed since last update.

【Rails】Deviseをカスタマイズして使いたい!! (導入〜モデル編)

Last updated at Posted at 2023-02-12

どうした?

Railsでアプリを作る際、ユーザー認証に便利なのがDevise gemです。
ただこのDevise、何でもかんでも言いなりに使用するとブラックボックス化してしまいます。
メソッドのようなおいしいところだけ使わさせて頂き、基本的な設計は自分の手でおこなうためにチャレンジしてみました。

Deviseを使う前に、Railsチュートリアル等で勉強して自分でユーザー認証できるようにしましょう。
Deviseもそう言ってます

今回目指すもの

今回目指すのは、以下のようなUserモデルです。

カラム 物理名 条件
id id integer
名前 name string 入力: 必須, 最大文字数: 50
Eメール email string 入力: 必須, ユニーク制限: あり, emailのrexexpを指定
パスワード password string 入力: 必須, 文字数範囲: 8~20

手順

準備

devise gemをGemfileに追加します。

Gemfile
gem 'devise'

記載したらbundle installしましょう。

ターミナルからdeviseをインストールします。

$ rails generate devise:install

通常はこの後認証用のメールサーバーを指定するのですが、今回メール認証はしないのでこの手順は飛ばします。

次に、日本語の設定をします。
詳細はこちらの記事をご覧ください。

Userモデルの作成

ターミナルにて以下のコマンドを実行します。

$ rails generate devise User

これにより、マイグレーションファイルとモデルファイルが生成されます。
これらを今回の実装に合わせて編集していきます。

マイグレーションファイル

20230208232147_devise_create_users
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: false # 追加
      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

# 略

      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

モデルファイル

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable, :recoverable, and :omniauthable
  devise :database_authenticatable, :registerable,
          :rememberable, :validatable #使用しないモジュール(:recoverable)はコメントアウト部分に移動

  validates :name,                presence: true,
                                  length: { maximum: 50 }

  validates :email,               presence: true,
                                  uniqueness: true

  validates :password,            presence: true
end

モデルファイルでは、モジュールの指定をすることができます。
各モジュールの機能については参考サイトをご覧ください。

設定が終わったらrails db:migrateでデータベースを作成しましょう。

テーブルが正しく作成されたか確認します。

terminal
$ rails c

User.columns.map(&:name)
=> ["id", "name", "email", "encrypted_password", "remember_created_at", "created_at", "updated_at"]

指定した通りのカラムが入っていることから、無事にテーブルが作成されたことが確認できました。

続いて、バリデーションの確認をします。
コンソールでNGデータのUserを作成し、返ってきたエラーメッセージを確認します。

terminal
$ rails c

# 空データを送信
User.create!
  TRANSACTION (0.4ms)  BEGIN
  User Exists? (1.1ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` = '' LIMIT 1
  TRANSACTION (0.5ms)  ROLLBACK
ActiveRecord::RecordInvalid: バリエーションに失敗しました: Eメール を入力してください, パスワード を入力してください, 名前 を入力してください, Eメール を入力してください, パスワード を入力してください

(※ エラーメッセージが日本語訳されていない場合は、準備の項で紹介した記事を元に設定してください)

エラーメッセージ中でEメールとパスワードが2回出現しています。
どうやらEメールとパスワードの必須条件はモデルファイルで指定したvalidatableモジュールに既に入っているようです。
モデルファイルを以下のように編集します。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable, :recoverable, and :omniauthable
  devise :database_authenticatable, :registerable,
          :rememberable, :validatable

  validates :name,                presence: true,
                                  length: { maximum: 50 }

  validates :email,               uniqueness: true # 必須条件を削除

  # passwordのバリデーションを削除
end

もう一度コンソールを開き、バリデーションを確認します。

terminal
$ rails c

# 必須入力の確認
User.create!
  TRANSACTION (0.3ms)  BEGIN
  TRANSACTION (0.4ms)  ROLLBACK
ActiveRecord::RecordInvalid: バリエーションに失敗しました: Eメール を入力してください, パスワード を入力してください, 名前 を入力してください

# nameの最大文字数、emailの形式、passwordの最小文字数を確認
User.create!(
  name: 'a'*51,
  email: 'sample',
  password: 'a')  
  TRANSACTION (0.3ms)  BEGIN
  TRANSACTION (1.3ms)  ROLLBACK
ActiveRecord::RecordInvalid: バリエーションに失敗しました: Eメール の形式が異なっています, パスワード 6文字以上で入力してください, 名前 50文字以内で入力してください

先程発生していたバリデーションの重複がクリアしていますね。
また、必須入力、nameの最大文字数もクリアしていることが分かります。
emailの形式指定も指定していないのになぜかクリアしています。
パスワード文字数について、6文字以上にするように怒られてしまいました(狙いは8文字以上)。

emailの形式やパスワードの文字数については指定していないのに、なぜバリデーションにかかるのでしょうか?
それは、deviseのvaridatableモジュールに元々組み込まれているからなのです。

config/initializers/devise.rbを開いてみましょう。
ここには、モジュールの設定値が記載されています。

config/initializers/devise.rb
Devise.setup do |config|
# 略
  config.password_length = 6..128

  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
# 略
end

と記載されているのが分かります。
ここで設定されているため、我々が改めてバリデーションを指定する必要がなかったのですね。
これらの設定を変えることで、バリデーションの指定を変更することができます。

config/initializers/devise.rb
Devise.setup do |config|
# 略
  config.password_length = 8..20 # 範囲を変更

  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ # 変更なし
# 略
end

設定したらコンソールで確認します。

terminal
$ rails c

User.create!(
  name: 'sample',
  email: 'sample@example.com',
  password: 'a')  
  TRANSACTION (1.7ms)  BEGIN
  TRANSACTION (0.5ms)  ROLLBACK
ActiveRecord::RecordInvalid: バリエーションに失敗しました: パスワード 8文字以上で入力してください

User.create!(
  name: 'sample',
  email: 'sample@example.com',  
  password: 'a'*21)  
  TRANSACTION (0.4ms)  BEGIN
  TRANSACTION (0.2ms)  ROLLBACK
ActiveRecord::RecordInvalid: バリエーションに失敗しました: パスワード 20文字以内で入力してください

パスワードの最小文字数と最大文字数についてのバリデーションが設定できていることが確認できました。

まとめ

今回の記事はここまでです。
引き続き、ルーティングの設定やコントローラの設定編をまとめていきます。

参考

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6