Is there a compact way with ActiveRecord to query for what id it\'s going to use next if an object was going to be persisted to the database? In SQL, a query like this would
Slightly better than the accepted answer:
YourModel.maximum(:id) + 1
Still prone to race-conditions etc, but at least it will take note of skipped ids and is slightly more efficient than, say, ordering the table by id then returning the last.
Here is slightly modified Taryn East's version:
Model.maximum(:id).next
If no one else is using the table (otherwise you would have to use locking), you could get the autoincrement value from MySQL, the SQL command is
SELECT auto_increment FROM information_schema.tables
WHERE table_schema = 'db_name' AND table_name = 'table_name';
and the Rails command would be
ActiveRecord::Base.connection.execute("SELECT auto_increment
FROM information_schema.tables
WHERE table_schema = 'db_name' AND table_name = 'table_name';").first[0]
Get the largest id on the table
YourModel.maximum(:id)
This will run the following sql
SELECT MAX("your_models"."id") AS max_id FROM "your_models"
Convert the result to an integer by calling to_i
. This is important as for an empty table the above max command will return nil
. Fortunately nil.to_i
returns 0
.
Now to get the next available id, just add 1 +
1`
The final result:
YourModal.maximum(:id).to_i+1
While accepting fig's answer I might want to draw your attention to a small thing. If you are getting the next ID to set to a particular record before saving, I think its not a good idea.
because as an example in a web based system
I'm not sure you want the last id to do what I'm thinking here, But if so this is just to draw your attention.
There seems to be need of a answer here that removes the race conditions, and addresses the actual problem of pre-providing unique identifiers.
To solve the problem you maintain a second model, which serves unique ID's for the primary model. This way you don't have any race condition.
If you need to make these ID's secure you should hash them with SHA256 (or SHA512) and store the hash as an indexed column on identifier model when they are generated.
They can then be associated and validated when used on the primary model. If you don't hash them you still associate them, to provide validation.
I'll post some example code a bit later.