はじめに
開発を行っているとenumを使って、データを分ける場合があると思います。
enumで分けたデータに対してそれぞれレコードの登録数を制限する実装をしたのでメモとして残しておきます。
開発環境
Rails 6.0.3
Ruby 2.7.1
テーブル
今回は下記のようなUsersテーブルを想定しています。
性別(sex)はenumでman/femaleのどちらかしか選択できないようにしています。
name | sex(enum) |
---|---|
ユーザー1 | man |
ユーザー2 | female |
レコード数を制限する方法
models/user.rbにメソッドを作成し、man/femaleそれぞれのレコード数を確認して、もし制限数(10件)を超えていればエラーを追加します。
on: :create
を記載しないと毎回バリデーションが適用され、編集できなくなってしまうので忘れないよう!
(私はここに気づかず編集の際にエラーが発生してしまいました。)
user.rb
class User < ApplicationRecord
REGISTER_LIMIT_COUNT = 10 # 定数として登録数を管理
enum sex: { man: 0, female: 1 }
validate :limit_user_register_count, on: :create # 作成したメソッドでバリデーション
def limit_user_register_count
if self.sex == "man" && man.count >= REGISTER_LIMIT_COUNT # enumがman かつ manのレコード数が制限を超えている
errors.add(:user, "man count is over") # エラーを追加
elsif self.sex == "female" && female.count >= REGISTER_LIMIT_COUNT
errors.add(:user, "female count is over")
end
end
end
Rspecでバリデーションを確認する方法
user_spec.rb
require 'rails_helper'
RSpec.describe Guide, type: :model do
context 'データを11個以上登録する場合' do
before { create_list(:user, 10, sex: 'man') } # manのデータをを10人分作成
it 'エラーメッセージを返すこと' do
man = build(:user, sex: 'man') # 11人目をbuildする(バリデーションがかかるのでcreateは不可)
man.valid? # validすることでcreateしようとしてvalidationが走り、エラーが追加される
expect(man.errors[:user]).to eq('man count is over')
end
end
end
factories/users.rb
FactoryBot.define do
factory :user do
name { Faker::Name.name }
sex { 0 }
end
end