Reputation: 7654
I'm attributing a unique code to each created item, to use in the URL. I do this during the item creation in the model:
class Item < ActiveRecord::Base
before_create { self.code = SecureRandom.urlsafe_base64 }
end
But I don't know if the generated code is really unique. Do I have to check the uniqueness during the creation, but this can take unnecessary time and resources if the Items table grows:
before_create :generate_unique_code
def generate_unique_code
loop do
code = SecureRandom.urlsafe_base64
unless Item.where(:code => code).any?
self.code = code
break
end
end
end
Can I trust the uniqueness of SecureRandom.urlsafe_base64
and skip the check?
Upvotes: 1
Views: 1797
Reputation: 373
Rails master branch includes one new module related to this. https://github.com/rails/rails/blob/master/activerecord/lib/active_record/secure_token.rb
Another solution you can reference.
Generating unique token on the fly with Rails
Upvotes: 0
Reputation: 168101
In order for it to be unique, it either has to (i) be following a rule that makes it never hit a previously generated output (such as by calling a one-to-one function on the time it was called, which only works under single thread), which makes it non-random, or (ii) keep a record of all previously generated outputs somewhere, which cannot be the case, and which also makes it non-random. In either case, you should be able to tell that is cannot be unique.
However, mathematics and engineering are different. Even if it is not unique, you can regard it as de facto unique. That is what programmers do.
Upvotes: 1
Reputation: 176402
Nothing is completely random in a computer generated string. Technically, there is a very low, remote possibility that two strings may be the same.
This is even more true in a highly concurrent system. If that's not the case, what you can do is to simply add an unique constraint (aka an unique index) at the database level. In this way, in the remote event that two strings will be equal, the database will reject the second one.
It's likely you will have an index on that field in any case if you need to use it for a query, therefore it should not add any unreasonable overhead.
As a side note, SecureRandom
is a Ruby library, not a Rails library.
Upvotes: 1