By default, the :id field is assumed to be a integer and is also a creatable field. Rails will happily pass on the :id supplied by the user to the database on creation, however, when using postgres subsequent creation attempts might fail.
Suppose we have two Posts in a table with ids 1 and 2. The next id rails postgres will try to create if there is no id supplied is given by SELECT nextval('posts_id_seq'), which is currently 3. If I send a POST request:
{ "data": { "type": "posts", "id": "3" } }
then I'll get a 201 response:
{ "data": { "type": "posts", "id": "3", "links": {...} } }
If I then POST a request without an id
{ "data": { "type": "posts" } }
then rails postgres will try to use the 3 supplied by nextval('posts_id_seq') and a uniqueness constraint is violated. This happens for every subsequent create request that doesn't specify a id.
There are two ways to fix this bug:
- only allow
:id to be a creatable field if it is an UUID, or
- call Post.connection.reset_pk_sequence! Post.table_name after a record with an explicit id is saved
I'm not sure if other databases suffer from the same problem.