It's the same in Ruby as in other languages where you want a loop to always run at least once: Move the condition to the end.
begin
code = ...
end until(Table.find_by(code: code).nil?)
Ruby's syntax is a little odd ("end until"), but it's the same as a do { ... } while()
in C-like languages.
However, the overall system you're using is really strange. If all you want is a unique number for the new table, just use id
. That's what it's for. It's set automatically at the database layer, so there'll be no collisions.
If you just want 4 random digits, don't make a random float (which may not have enough digits, e.g. 0.0), convert it to a string and pull out a section. Just call rand(1000..9999).to_s
. Or rand(10_000).to_s.rjust(4, '0')
to get a number padded with leading zeros if necessary.
However, anything you do in the application layer is vulnerable to race conditions! Between the time you check if a code already exists in the database, and the time you save your record, that code may have been added, giving you duplicates. E.g. 2 threads both check for the code 1234
at the same time, and both see that it's not in the database, so both then save records with that same code. Oops.
The proper way to avoid such things is to add a uniqueness constraint in the database itself, and rescue the resulting RecordNotUnique
error that'll get raised.
Here's an article discussing other ways to generate unique tokens, and a follow-up on how to handle collisions.
However: just use id
. Or find a gem that generates unique tokens for you.