Reputation: 5172
Currently trying to generate a random number in a specific range; and ensure that it would be unique against others stored records.
Using Mysql. Could be like an id, incremented; but can't be it.
Currently testing other existing records in an 'expensive' manner; but I'm pretty sure that there would be a clean 1/2 lines of code to use
Currently using :
test = 0
Order.all.each do |ord|
test = (0..899999).to_a.sample.to_s.rjust(6, '0')
if Order.find_by_number(test).nil? then
break
end
end
return test
Thanks for any help
Upvotes: 1
Views: 204
Reputation: 4860
Here your are my one-line solution. It is also the quicker one since calls .pluck
to retrieve the numbers from the Order table. .select
instantiates an "Order" object for every record (that is very costly and unnecessary) while .pluck
does not. It also avoids to iterate again each object with a .map
to get the "number" field. We can avoid the second .map
as well if we convert, using CAST
in this case, to a numeric value from the database.
(Array(0...899999) - Order.pluck("CAST('number' AS UNSIGNED)")).sample.to_s.rjust(6, '0')
Upvotes: 2
Reputation: 118271
I think, you can do something like below :
def uniq_num_add(arr)
loop do
rndm = rand(1..15) # I took this range as an example
# random number will be added to the array, when the number will
# not be present
break arr<< "%02d" % rndm unless arr.include?(rndm)
end
end
array = []
3.times do
uniq_num_add(array)
end
array # => ["02", "15", "04"]
Upvotes: 1
Reputation: 37409
I would do something like this:
# gets all existing IDs
existing_ids = Order.all.select(:number).map(&:number).map(&:to_i)
# removes them from the acceptable range
available_numbers = (0..899999).to_a - existing_ids
# choose one (which is not in the DB)
available_numbers.sample.to_s.rjust(6, '0')
Upvotes: 1