Rails создает уникальную ценность для сохранения в базе данных - PullRequest
0 голосов
/ 09 мая 2020

Я имею в виду не проверять при сохранении, является ли текущее значение уникальным.

Как я могу создать значение (например, в моей модели), проверьте, является ли оно уникальным для моей таблицы. Anf id, возможно, не стоит пытаться создать новое значение. И еще раз проверим уникальность

Теперь у меня в модели есть такой код:

  after_initialize :init

  def init
    self.some_field = rand(1..99_999_999).to_s
  end

Ответы [ 4 ]

1 голос
/ 10 мая 2020

Недавно я написал гем, чтобы решить эту проблему для себя: https://github.com/inem/shufflino

При таком подходе не требуется повторных попыток или дополнительных запросов SQL.

I так же рекомендую посмотреть этот разговор на топи c.

1 голос
/ 09 мая 2020

Вы можете использовать обратный вызов модели, например,

before_create :generate_token

def generate_some_field
  self.some_field = loop do
    random = rand(1..99_999_999).to_s
    break random unless ModelName.exists?(some_field: random)
  end
end
1 голос
/ 09 мая 2020

Добавьте проверку на уникальность и инициализируйте поле перед проверкой. Добавьте ограничение на максимальное количество повторений, чтобы избежать возможных взаимоблокировок, когда количество записей приближается или достигает максимального количества возможных случайных значений.

  INITIALIZATION_MAX_RETRIES = 10
  before_validation :initialize_fields

  validates_uniqueness_of :some_field

  private

  def initialize_fields
    unless some_field
      retries = 0
      loop do
        retries += 1
        break if retries > INITIALIZATION_MAX_RETRIES

        self.some_field = rand(1..99_999_999).to_s
        break unless self.class.find_by(some_field: some_field)
      end
    end
  end
1 голос
/ 09 мая 2020

Добавьте проверку

Затем установите значение, проверьте его,

если хорошо: готово.

если нет: попробуйте еще раз, повторив разумное количество раз.

Примерно так

 validates :some_field, uniqueness: true 

 def init
    attempts = 0
    loop do
      self.some_field  <<  SecureRandom.uuid.to_s[0..16]
      self.valid?
      break unless self.errors[:some_field].any?
      attempts = attempts + 1
      if attempts > 3
         self.errors[:some_field] << "Could not generate a unique value after #{attempts} attempts"
         break
      end
    end

  end
...