While procrastinating working on a new Rails app, I didn’t want object IDs to start at 1 but neither did I want to deal with the various hassles of using a UUID instead of an integer for the ID. My compromise was to start the ID numbering with a multiple digit number.
This requires adding an execute
statement (which is technically non-reversible) to your create_table
migration:
class CreateUsers < ActiveRecord::Migration[7.1]
def change
create_table :users do |t|
t.string :name, null: false
t.string :email, null: false
t.timestamps
end
reversible do |direction|
direction.up do
# Set the starting ID on the users table so IDs don't start at 1
execute <<-SQL
INSERT INTO sqlite_sequence ('name', 'seq') VALUES('users', 2345);
SQL
end
direction.down do
# Do nothing (entry is automatically removed when table is dropped)
end
end
end
end
Note: The relevant sequence row gets dropped when the table gets dropped, so in this case there’s no need to define a down
action. I’ve included an empty one anyway to make it clear this isn’t an oversight.
Now when I create my first user, their ID is 1 higher than the sequence I assigned… app.example.com/users/2346
.
You can choose whatever starting number you want. If you’re running this on a different table, replace the ‘users’ portion with your own table name:
INSERT INTO sqlite_sequence ('name', 'seq') VALUES('<table>', 1734);
The above example is specific to SQLite (I’m using Litestack to simplify deployment) but presumably you could do something very similar with other databases.
I haven’t tested this but for PostgreSQL it should be as simple as changing the execute
command above to:
SELECT setval('users_id_seq', 2345);
-- '<table>_id_seq' for other table names
If you try this with PostgreSQL, make you sure test the migration works in both directions.