How do I get ActiveRecord to show the next id (last + 1) in Ruby on Rails?

前端 未结 13 1231
臣服心动
臣服心动 2020-12-05 06:33

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

相关标签:
13条回答
  • 2020-12-05 06:50

    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.

    0 讨论(0)
  • 2020-12-05 06:52

    Here is slightly modified Taryn East's version:

    Model.maximum(:id).next
    
    0 讨论(0)
  • 2020-12-05 06:55

    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]
    
    0 讨论(0)
  • 2020-12-05 06:57

    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
    
    0 讨论(0)
  • 2020-12-05 06:58

    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

    1. you get the last id as 10
    2. you set the next id as 11
    3. before you save the record someone else has saved the record, now the last id should be 12 likewise..

    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.

    0 讨论(0)
  • 2020-12-05 07:00

    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.

    0 讨论(0)
提交回复
热议问题