0
0

More than 1 year has passed since last update.

【Ruby/Rails】クラスでユニークな(一意となる)値を設定する

Last updated at Posted at 2020-05-26

rubocopでは、loop + break を推奨されます。

loop + break版

class Nonce
  def set_nonce
    return true if nonce.present? # 上書きさせないためのガード

    self.nonace = loop do
      random_str = SecureRandom.urlsafe_base64
      break random_str unless self.class.exists?(nonce: random_str)
    end
  end
end

while版

class Nonce
  def set_nonce
    return true if nonce.present? # 上書きさせないためのガード

    begin
      self.nonce = SecureRandom.urlsafe_base64
    end while self.class.exists?(nonce: nonce)
  end
end

before_create or before_validation

以下のような感じで、validates を書いている場合は、before_create を使うと、validation に引っかかってしまうので、before_validation を使う必要があります。

class SomeClass
  validates :nonce, presence: true, uniqueness: true

  before_validation :set_nonce

  private

  def set_nonce
    return true if nonce.present?

    self.nonce = loop do
      random_str = SecureRandom.urlsafe_base64
      break random_str unless self.class.exists?(nonce: random_str)
    end
  end
end

テストの例

# frozen_string_literal: true

require 'rails_helper'

describe Nonce, type: :model do
  describe '#set_nonce' do
    it do
      nonce = Nonce.create!
      expect(nonce.nonce.size).to eq(8)
    end

    it do
      nonce = Nonce.new
      expect(nonce.nonce).to be_nil
      nonce.save!
      expect(nonce.nonce.size).to eq(8)
    end

    it do
      nonce = Nonce.create!
      nonce_str = nonce.nonce
      nonce.update!(updated_at: Time.current)
      expect(nonce.nonce).to eq(nonce_str)
    end
  end
end
0
0
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
0
0