deviseを使用したuserモデルバリデーションチェックのRSpec初コーディング（後編）

バリデーションもかかってやっと後半に向かえました。

目的
-

・氏名（漢字）の半角登録禁止バリデーションとテスト
・氏名カナの半角カタカナ禁止バリデーションとテスト
・メールアドレスの重複チェック
・＠のないアドレスチェックテスト

＊ユーザー登録の終わりは見えてきました。

これまでの経過
-

・RSpecインストール
・FactoryBotインストール
・Fakerインストール
・Gimeiインストール
・異常系テスト実装「〜can't be blank」
・６文字混合パスワード設定（Faker）
・カタカナ・漢字ダミーデータ設定（Gimei）
・パスワード・カタカナ漢字全角設定のための正規表現の学習
・バリデーションのまとめかた with_options
・追加でvalidatableについて

Ruby on rails モデル単体テストでのメールアドレス二重登録テストについて
>###https://qiita.com/takuo_maeda/items/ae15efd9adcd38d7d323

目的１：半角カタカナ文字変換
-

Gimeiを使って全角カタカナを作った後で
Rubyでの半角全角の変換はNKFで行います。

NKFとは
-

Linuxの基本的なコマンド、「nkf」は「Network Kanji Filter」の略です。

|オプション|意味     |
|:---|---:|
|-w|UTF-8コードを出力する（BOMなし）|
|-Z4|半角カナ文字を渡した場合に全角カナ文字/半角カタカナを渡した場合その逆に|

さらに-xオプションを追加すると半角カナしか出力されないようにできます。

```terminal:terminal
NFK.nfk("-w -x -Z4", "ｱﾅｽﾀｼｱ")
 => "ｱﾅｽﾀｼｱ"
```

参考:なえ様
>https://310nae.com/text-conversion/

メールアドレスの一意性
-

すでに登録のあるメールアドレスは新規登録用には使えない仕様にすること。

私がQiitaに掲載した初記事です。よかったら

>https://qiita.com/takuo_maeda/items/ae15efd9adcd38d7d323

```ruby:spec/models/user_spec.rb
    it '同じメールアドレスを登録できないこと' do
      user1 = FactoryBot.create(:user)
      @user.email = user1.email
      @user.valid?
      expect(@user.errors.full_messages).to include("Email has already been taken")
    end
```

FactoryBot.createでいったん作っただみデータを保存。
その後、user1.emailで先ほど作っただみデータを呼び出すだけです。
＊基本のエラーメッセージは"Email has already been taken"です。

@のないメールははじく
-

```rb:spec/models/user_spec.rb
    it '@のないメールアドレスを登録できないこと' do
      @user.email = Faker::Lorem.characters(number: 10, min_alpha: 10) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Email is invalid")
    end
```

Fakerで文字列を作るだけでOKです。
＊基本のエラーメッセージは"Email is invalid"です。

前半後半と長いことお付き合いいただきまして誠にありがとうございました。

書いたバリデーションとテストです。
-

```rb:app/models/user.rb
class User < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  
  with_options presence: true do
    validates :nickname, :birthday, :password_confirmation
    validates :first_name, :last_name, format: { with: /\A[ぁ-んァ-ン一-龥々]/, message: "は全角ひらがな、全角カタカナ、漢字で入力して下さい" }
    validates :last_name_prono, :first_name_prono, format: { with: /\A[ァ-ヶー－]+\z/, message: "は全角カタカナで入力して下さい" }
  end
  validates :password, :password_confirmation,
  format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i, message: "は半角英数で入力して下さい" }
end
```

```rb:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    nickname {Faker::Name.last_name}
    email {Faker::Internet.free_email}
    password {Faker::Lorem.characters(number: 6, min_alpha: 1, min_numeric: 1) }
    password_confirmation {password}
    first_name { Gimei.first.kanji }
    last_name { Gimei.last.kanji }
    first_name_prono { Gimei.first.katakana }
    last_name_prono { Gimei.last.katakana }
    birthday { Faker::Date.backward }
    # password_short {Faker::Lorem.characters(number: 5, min_alpha: 1, min_numeric: 1) }
    # password_alpha {Faker::Lorem.Alpanameric.alpa(number: 6) }
    # password_number {Faker::Lorem.Number(6) }
  end
end
```

```rb:spec/models/user_spec.rb

require 'rails_helper'

RSpec.describe User, type: :model do
  describe '#create' do
    before do
      @user = FactoryBot.build(:user)
    end

    it 'nickame,email,password,password_comfirmation,first_name,last_name,first_name_prono,last_name_prono,birthdayの値が存在すれば登録できること' do
      expect(@user).to be_valid
    end

    it 'nicknameが空では登録できないこと' do
      @user.nickname = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Nickname can't be blank")
    end

    it 'emailが空では登録できないこと' do
      @user.email = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Email can't be blank")
    end

    it '同じメールアドレスを登録できないこと' do
      user1 = FactoryBot.create(:user)
      @user.email = user1.email
      @user.valid?
      expect(@user.errors.full_messages).to include("Email has already been taken")
    end

    it '@のないメールアドレスを登録できないこと' do
      @user.email = Faker::Lorem.characters(number: 10, min_alpha: 10) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Email is invalid")
    end

    it 'paswordが空では登録できないこと' do
      @user.password = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Password can't be blank", "Password confirmation doesn't match Password", "Password は半角英数で入力して下さい")
    end

    it 'paswordが文字数５文字では登録できないこと' do
      @user.password = Faker::Lorem.characters(number: 5, min_alpha: 1, min_numeric: 1) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Password is too short (minimum is 6 characters)")
    end
  
    it 'paswordが半角アルファベットでは登録できないこと' do
      @user.password = Faker::Lorem.characters(number: 6, min_alpha: 6) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Password は半角英数で入力して下さい")
    end

    it 'paswordが数字のみでは登録できないこと' do
      @user.password = Faker::Lorem.characters(number: 6, min_numeric:6) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Password は半角英数で入力して下さい")
    end

    it 'paswordが全角英数のみでは登録できないこと' do
      password_zen = Faker::Lorem.characters(number: 1, min_numeric:1) 
      require 'nkf'
      password_zen.tr("A-Z0-9","Ａ-Ｚ０-９")
      @user.password = password_zen
      @user.valid?
      expect(@user.errors.full_messages).to include("Password は半角英数で入力して下さい")
    end

    it 'pasword_confirmationが空では登録できないこと' do
      @user.password_confirmation = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Password confirmation は半角英数で入力して下さい")
    end

    it 'passworとpasword_confirmationが一致しないと登録できないこと' do
      @user.password = Faker::Lorem.characters(number: 7, min_alpha: 3, min_numeric: 1) 
      @user.password_confirmation =  Faker::Lorem.characters(number: 6, min_alpha: 3, min_numeric: 2) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Password confirmation doesn't match Password")
    end

    it 'pasword_confirmationが文字数５文字では登録できないこと' do
      @user.password_confirmation = Faker::Lorem.characters(number: 5, min_alpha: 1, min_numeric: 1) 
      @user.valid?
      expect(@user.errors.full_messages).to include("Password confirmation doesn't match Password")
    end

    it 'first_nameが空では登録できないこと' do
      @user.first_name = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("First name can't be blank")
    end

    it 'last_nameが空では登録できないこと' do
      @user.last_name = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Last name can't be blank")
    end

    it 'first_nameが半角では登録できないこと' do
      @user.first_name = Faker::Alphanumeric.alphanumeric(number: 4)
      @user.valid?
      expect(@user.errors.full_messages).to include("First name は全角ひらがな、全角カタカナ、漢字で入力して下さい")
    end

    it 'last_nameが半角では登録できないこと' do
      @user.last_name = Faker::Alphanumeric.alphanumeric(number: 4)
      @user.valid?
      expect(@user.errors.full_messages).to include("Last name は全角ひらがな、全角カタカナ、漢字で入力して下さい")
    end

    it 'first_name_pronoが空では登録できないこと' do
      @user.first_name_prono = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("First name prono can't be blank")
    end
 
    it 'last_name_pronoが空では登録できないこと' do
      @user.last_name_prono = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Last name prono can't be blank")
    end

    it 'first_name_pronoが半角では登録できないこと' do
      require 'nkf'
      first_half_kana = Gimei.first.katakana
      @user.first_name_prono = NKF.nkf('-w -Z4 -x', first_half_kana)
      @user.valid?
      expect(@user.errors.full_messages).to include("First name prono は全角カタカナで入力して下さい")
    end

    it 'last_name_pronoが半角では登録できないこと' do
      require 'nkf'
      last_half_kana = Gimei.last.katakana
      @user.first_name_prono = NKF.nkf('-w -Z4 -x', last_half_kana)
      @user.last_name_prono = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Last name prono は全角カタカナで入力して下さい")
    end

    it 'birthdayが空では登録できないこと' do
      @user.birthday = ''
      @user.valid?
      expect(@user.errors.full_messages).to include("Birthday can't be blank")
    end
  end
end
```