Setting unique code to model before creating (ruby/rails) I have a Table model that needs a unique code. I have a method creating the code (and making sure it's unique), but I have the same line self.code = rand.to_s[2..5] twice. Is there a neat way to only have that line once?

class Table &lt; ActiveRecord::Base
  before_create :set_code

  private
  def set_code
    self.code = rand.to_s[2..5]
    while(Table.find_by(code: code) != nil)
      self.code = rand.to_s[2..5]
    end
  end
end
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.