3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【rails】enumのレコード登録数をバリデーションで制限する方法

Posted at

はじめに

開発を行っていると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
3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?